Ответ 1
Проблема здесь не в строгом псевдониме, а в требованиях представления структуры.
Во-первых, это безопасно для псевдонимов между char
, signed char
или unsigned char
и любым другим типом (в вашем случае unsigned int
). Это позволяет вам писать свои собственные циклы копирования памяти, так как поскольку они определены с использованием типа char
. Это разрешено в C99 (§6.5) следующим языком:
6. Эффективным типом объекта для доступа к его сохраненному значению является объявленный тип объекта, если таковой имеется. [Сноска: Выделенные объекты не имеют объявленного типа] [...] Если значение копируется в объект, не имеющий объявленного типа, используя memcpy или memmove, или копируется как массив типа символа, тогда эффективный тип измененного объекта для этого доступа и для последующих доступов, которые не изменяют value - это эффективный тип объекта, из которого копируется значение, если оно есть. Для все другие обращения к объекту, не имеющему объявленного типа, эффективный тип объекта просто тип lvalue, используемый для доступа.
7. Объект должен иметь сохраненное значение, доступ к которому имеет только выражение lvalue, которое имеет один из следующих типов: [Сноска: Цель этого списка состоит в том, чтобы указать те обстоятельства, в которых объект может быть или не быть псевдонимом.]
- тип, совместимый с эффективным типом объекта,
- [...]
- тип символа.
Сходный язык можно найти в черновик С++ 0x N3242 §3.11/10, хотя это не так ясно, когда назначается "динамический тип" объекта (я буду благодарен за любые дальнейшие ссылки на то, что динамическое type имеет массив char, к которому объект POD был скопирован как массив char с правильным выравниванием).
Таким образом, сглаживание здесь не является проблемой. Тем не менее, строгое чтение стандарта указывает на то, что реализация С++ имеет большую свободу в выборе представления unsigned int
.
В качестве одного случайного примера unsigned int
может быть 24-разрядным целым числом, представленным в четырех байтах, с 8 переполненными битами заполнения; если какой-либо из этих битов дополнений не соответствует определенному (постоянному) шаблону, он рассматривается как ловушечное представление, и разыменование указателя приведет к сбою. Является ли это вероятной реализацией? Возможно нет. Но были исторически системы с битами четности и другой странностью, и поэтому прямое считывание из сети в unsigned int
путем строгого чтения стандарта не является кошерным.
Теперь проблема заполнения битов в большинстве случаев является теоретической проблемой для большинства систем, но стоит отметить. Если вы планируете придерживаться аппаратного обеспечения ПК, вам не нужно беспокоиться об этом (но не забывайте, что ваш ntohl
- endianness все еще проблема!)
Структуры делают это еще хуже, конечно - представления выравнивания зависят от вашей платформы. Я работал над встроенной платформой, в которой все типы имеют выравнивание 1 - никакие дополнения никогда не вставляются в структуры. Это может привести к несогласованности при использовании тех же определений структуры на нескольких платформах. Вы можете вручную выработать смещения байтов для элементов структуры данных и напрямую ссылаться на них или использовать директиву для определения соответствия для компилятора для контроля заполнения.
Таким образом, вы должны быть осторожны при прямом литье из сетевого буфера в собственные типы или структуры. Но само это наложение не является проблемой.