liés, mais un peu différent de Do any compilers transfer effective type through memcpy/memmovetype agnostique memcpy dans C99
En C89, memcpy
et memmove
sont tenus de se comporter comme si la source et la destination sont accessibles en utilisant des types de caractères, la copie de tous les bits du source à la destination sans tenir compte du type de données en cours de copie. C99 modifie la sémantique de sorte que si un objet avec un type effectif est copié dans un stockage qui n'a pas de type déclaré [généralement un stockage reçu de malloc ou une autre fonction similaire], il crée un objet dans le stockage de destination accessible uniquement en utilisant le type de source. Le code suivant, par exemple, aurait un comportement entièrement défini en C89 sur toutes les plates-formes où "unsigned int" et "unsigned long" ont la même représentation 32 bits, mais auraient un comportement indéfini sous 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;
}
En vertu des règles C99, en passant le stockage alloué à la fonction « increment_32_bit_uint », il sera fixé le type efficace pour uint32_t, qui ne peut pas être le même type que les deux « non signé » et « unsigned long », même si les trois les types ont la même représentation. Par conséquent, un compilateur peut faire tout ce qu'il veut avec du code qui lit ce stockage comme un type autre que uint32_t, même si ce type a la même représentation. Y a-t-il un moyen, en C99 ou C11, d'effectuer la copie de manière à permettre à un compilateur de générer du code efficace, mais de forcer le compilateur à traiter la destination comme s'il contenait un motif de bits sans type effectif [qui pourrait donc être accessible en utilisant n'importe quel type]?
gcc compile votre exemple sans avertissement en utilisant 'std = c99' ou' std = c11' après y compris '' et '' –
xvan
@xvan: Qu'un compilateur particulier (ou même chaque compilateur qui existe aujourd'hui) arrive à faire quelque chose ne signifie pas que la norme impose une exigence de continuer à le faire.Il y a un certain nombre de cas où presque tous les compilateurs ont eu un comportement identique pendant des décennies sans que la norme ne le leur impose, jusqu'à ce que certains auteurs de compilateurs décident qu'ils n'ont plus besoin de prendre en charge ces cas. compilateurs ne signifie pas qu'il n'invoque pas UB. – supercat
@xvan: Per N1570: "Si une valeur est copiée dans un objet sans type déclaré en utilisant memcpy ou memmove, ou est copiée comme un tableau de type caractère, alors le type effectif de l'objet modifié pour cet accès et pour les accès suivants qui ne modifie pas la valeur est le type effectif de l'objet à partir duquel la valeur est copiée, s'il en a un. " Je ne vois aucune raison de dire que le type effectif ne serait pas défini sur 'uint32_t', ni que la lecture comme tout autre type n'invoquerait pas de comportement indéfini. – supercat