Разрешено ли приведение из TYPE* в unsigned char*?
C99 - в частности, раздел 6.2.6.1, параграф 4 - гласит, что копирование представления объекта в массив беззнаковых символов допускается:
struct {
int foo;
double bar;
} baz;
unsigned char bytes[sizeof baz];
// Do things with the baz structure.
memcpy(bytes, &baz, sizeof bytes);
// Do things with the bytes array.
Мой вопрос: не можем ли мы избежать дополнительного выделения памяти и операции копирования простым приведением? Например:
struct {
int foo;
double bar;
} baz;
unsigned char *bytes = (void *)&baz;
// Do stuff with the baz structure.
// Do things with the bytes array.
Конечно, размер должен быть отслежен, но это в первую очередь законно, или он относится к сфере, определяемой реализацией или неопределенным поведением?
Я спрашиваю, потому что я реализую алгоритм, аналогичный qsort
, и я хотел бы, чтобы он работал для любого массива, независимо от типа, так же, как qsort
делает.
1 ответ
6.5 Выражения
[...]
6 Эффективным типом объекта для доступа к его сохраненному значению является объявленный тип объекта, если таковой имеется.87) Если значение сохраняется в объекте, у которого нет объявленного типа, через lvalue, имеющий тип, который не является символом type, тогда тип lvalue становится эффективным типом объекта для этого доступа и для последующих обращений, которые не изменяют сохраненное значение. Если значение копируется в объект, не имеющий объявленного типа, с использованием memcpy или memmove, или копируется как массив символьного типа, тогда эффективный тип измененного объекта для этого доступа и для последующих доступов, которые не изменяют значение, является действующий тип объекта, из которого копируется значение, если оно есть. Для всех других доступов к объекту, не имеющему объявленного типа, эффективный тип объекта - это просто тип lvalue, используемого для доступа.
7 Объект должен иметь свое сохраненное значение, доступ к которому осуществляется только через выражение lvalue, имеющее один из следующих типов:88)
- тип, совместимый с эффективным типом объекта,
- квалифицированная версия типа, совместимого с эффективным типом объекта,
- тип, который является типом со знаком или без знака, соответствующим действующему типу объекта,
- тип, который является типом со знаком или без знака, соответствующим квалифицированной версии действующего типа объекта,
- тип агрегата или объединения, который включает в себя один из вышеупомянутых типов среди своих членов (включая, рекурсивно, член субагрегата или автономного объединения), или
- тип персонажа.
Акцент мой. Таким образом, вы можете рассматривать любой тип как массив символов (unsigned char[]
, char[]
или же signed char[]
).
Я также процитировал пункт 6, потому что он делает обратное неприменимым.