Можно ли использовать memcpy для штамповки типов?

Это цитата из стандарта C11:

6.5 Выражения
...

6эффективный тип объекта для доступа к его сохраненному значению является объявленным типом объекта, если таковой имеется. Если значение сохраняется в объекте, у которого нет объявленного типа, через lvalue, имеющий тип, который не является символьным типом, то тип lvalue становится эффективным типом объекта для этого доступа и для последующих доступов, которые не изменяют сохраненное значение. Если значение копируется в объект, не имеющий объявленного типа, используяmemcpy или жеmemmoveили копируется как массив символьного типа, тогда эффективный тип модифицированного объекта для этого доступа и для последующих доступов, которые не изменяют значение, является эффективным типом объекта, из которого копируется значение, если оно имеет , Для всех других обращений к объекту, у которого нет объявленного типа, эффективный тип объекта - это просто тип lvalue, используемого для доступа.

7 Объект должен иметь свое сохраненное значение, доступное только через выражение lvalue, которое имеет один из следующих типов:

- тип, совместимый с эффективным типом объекта,
- квалифицированная версия типа, совместимого с эффективным типом объекта,
- тип, который является типом со знаком или без знака, соответствующим действующему типу объекта,
- тип, который является типом со знаком или без знака, соответствующим квалифицированной версии действующего типа объекта,
- агрегатный или объединенный тип, который включает один из вышеупомянутых типов среди своих членов (включая, рекурсивно, член субагрегированного или автономного объединения), или
- тип персонажа.

Означает ли это, чтоmemcpy не может использоваться для типа наказания таким образом:

double d = 1234.5678;
uint64_t bits;
memcpy(&bits, &d, sizeof bits);
printf("the representation of %g is %08"PRIX64"\n", d, bits);

Почему бы не дать такой же вывод, как:

union { double d; uint64_t i; } u;
u.d = 1234.5678;
printf("the representation of %g is %08"PRIX64"\n", d, u.i);

Что делать, если я использую свою версиюmemcpy используя типы символов:

void *my_memcpy(void *dst, const void *src, size_t n) {
    unsigned char *d = dst;
    const unsigned char *s = src;
    for (size_t i = 0; i < n; i++) { d[i] = s[i]; }
    return dst;
}

РЕДАКТИРОВАТЬ: EOF отметил, чтоЧасть оmemcpy() в пункте 6 не применяется в этой ситуации, так какuint64_t bits имеет объявленный тип. Я согласен, но, к сожалению, это не помогает ответить на вопросmemcpy может использоваться для типа наказания, просто делает пункт 6 неуместным для оценки достоверности приведенных выше примеров.

Вот еще одна попытка напечататьmemcpy Я полагаю, что это будет охватываться пунктом 6:

double d = 1234.5678;
void *p = malloc(sizeof(double));
if (p != NULL) {
    uint64_t *pbits = memcpy(p, &d, sizeof(double));
    uint64_t bits = *pbits;
    printf("the representation of %g is %08"PRIX64"\n", d, bits);
}

Если предположить,sizeof(double) == sizeof(uint64_t)Имеет ли вышеуказанный код определенное поведение в соответствии с пунктами 6 и 7?

РЕДАКТИРОВАТЬ: Некоторые ответы указывают на возможность неопределенного поведения, возникающего при чтении представления ловушки. Это не имеет значения, поскольку Стандарт C явно исключает эту возможность:

7.20.1.1 Целочисленные типы с точной шириной

1 имя типа определенияintN_t обозначает целочисленный тип со знаком с ширинойN, без дополнительных битов и представления дополнения до двух. Таким образом,int8_t обозначает такой целочисленный тип со знаком шириной ровно 8 бит.

2 Имя типа определенияuintN_t обозначает целочисленный тип без знака с ширинойN и нет битов заполнения. Таким образом,uint24_t обозначает такой целочисленный тип без знака с шириной ровно 24 бита.

Эти типы не являются обязательными. Однако, если реализация предоставляет целочисленные типы с шириной 8, 16, 32 или 64 бита, без битов заполнения и (для подписанных типов), которые имеют представление дополнения до двух, она должна определять соответствующие имена typedef.

Типuint64_t имеет ровно 64 значения битов и не имеет битов заполнения, поэтому не может быть никаких представлений прерываний.

Ответы на вопрос(5)

Ваш ответ на вопрос