Связанных, но несколько отличается от, Do any compilers transfer effective type through memcpy/memmoveтипа агностика тетсра в C99
В C89, memcpy
и memmove
должны вести себя так, как будто источник и назначение доступны с использованием типов символов, копированием всех бит источник для адресата без учета типа копируемых данных.
C99 изменяет семантику так, что если объект с эффективным типом копируется в хранилище, у которого нет объявленного типа [обычно это память, полученная от malloc или другой такой функции], он создает объект в целевом хранилище, к которому можно получить доступ используя тип источника.
В следующем коде, например, было бы полностью определено поведение в C89 на всех платформах, где «unsigned int» и «unsigned long» имеют одно и то же 32-битное представление, но имели бы Undefined Behavior под C99.
#include <stdio.h>
#include <string.h>
void increment_32_bit_uint(void *p)
{
uint32_t temp;
memcpy(&temp, p, sizeof temp);
temp++;
memcpy(p, &temp, sizeof temp);
}
int main(void)
{
unsigned *ip = malloc(sizeof (unsigned));
unsigned long *lp = malloc(sizeof (unsigned long));
*ip = 3; *lp = 6;
increment_32_bit_uint(ip);
increment_32_bit_uint(lp);
printf("%u %lu", *ip, *lp);
return 0;
}
Согласно правилам C99, передавая выделенную память для функции «increment_32_bit_uint» сделает это установить эффективный тип для uint32_t, которая не может быть такого же типа, как и «без знака» и «без знака долго», даже если все три типы имеют одинаковое представление. Следовательно, компилятор может делать все, что ему нравится, с кодом, который читает это хранилище как тип, отличный от uint32_t, даже если этот тип имеет такое же представление.
Есть ли способ на C99 или C11 выполнить копию таким образом, чтобы компилятор мог генерировать эффективный код, но заставил компилятор обрабатывать адресат так, как если бы он содержал шаблон бит без эффективный тип [который можно было бы получить с помощью любого типа]?
GCC компилирует пример с предупреждения не используя '-std = c99' или' -std = c11' после включения '' и '' –
xvan
@xvan: Это конкретный компилятор (или даже каждый компилятор, который существует сегодня) что-то не означает, что Стандарт налагает какое-либо требование продолжать это делать.Существует несколько случаев, когда почти каждый существующий компилятор имел одинаковое поведение в течение десятилетий, не требуя от них Стандарта, пока некоторые авторы компилятора не решили, что им больше не нужно поддерживать эти случаи, поэтому тот факт, что код работает на всех сегодняшних компиляторы не означает, что он не вызывает UB. – supercat
@xvan: Per N1570: «Если значение копируется в объект, не имеющий объявленного типа с использованием memcpy или memmove, или копируется как массив типа символа, тогда эффективный тип измененного объекта для этого доступа и для последующего доступа которые не изменяют значение, является эффективным типом объекта, из которого копируется значение, если оно есть. " Я не вижу оснований говорить, что эффективный тип не будет установлен в 'uint32_t', и это чтение, поскольку любой другой тип не будет вызывать Undefined Behavior. – supercat