Je suis tombé sur le puzzle C suivant:
Q: Pourquoi le programme suivant se bloque-t-il sur IA-64, mais fonctionne-t-il correctement sur IA-32?
int main()
{
int* p;
p = (int*)malloc(sizeof(int));
*p = 10;
return 0;
}
Je sais que la taille de int
sur une machine 64 bits peut ne pas être la même que la taille d'un pointeur (int
pourrait être 32 bits et le pointeur pourrait être 64 bits). Mais je ne sais pas comment cela se rapporte au programme ci-dessus. Des idées?
Le transtypage en int*
Masque le fait que sans le #include
Approprié, le type de retour de malloc
est supposé être int
. IA-64 se trouve avoir sizeof(int) < sizeof(int*)
ce qui rend ce problème évident.
(Notez également qu'en raison du comportement non défini, il peut toujours échouer même sur une plate-forme où sizeof(int)==sizeof(int*)
est vraie, par exemple si la convention d'appel utilise des registres différents pour renvoyer des pointeurs que des entiers)
comp.lang.c FAQ a une entrée discutant pourquoi la conversion du retour de malloc
n'est jamais nécessaire et potentiellement mauvaise .
Très probablement parce que vous êtes non compris le fichier d'en-tête pour malloc
et, bien que le compilateur vous en avertisse normalement, le fait que vous convertissez explicitement la valeur de retour signifie que vous dis-lui que tu sais ce que tu fais.
Cela signifie que le compilateur s'attend à ce qu'un int
soit renvoyé de malloc
qu'il convertit ensuite en un pointeur. S'ils sont de tailles différentes, cela vous causera du chagrin.
C'est pourquoi vous jamais transformez le retour malloc
en C. Le void*
qu'il retourne sera implicitement converti en un pointeur du type correct (à moins que vous n'ayez pas inclus l'en-tête, auquel cas il vous aurait probablement averti de la conversion int-pointer-to-pointer potentiellement dangereuse).
C'est pourquoi vous ne compilez jamais sans avertissements sur les prototypes manquants.
C'est pourquoi vous ne lancez jamais le retour malloc en C.
Le cast est nécessaire pour la compatibilité C++. Il y a peu de raisons (lire: aucune raison ici) de l'omettre.
La compatibilité C++ n'est pas toujours nécessaire, et dans certains cas pas possible du tout, mais dans la plupart des cas, elle est très facilement réalisée.