Casting deux fois dans la même ligne

J’ai vu ce code dans le projet.

Le type de b est void* :

 void *b = ...; int a = (int) (unsigned long) b; 

Cette ligne est-elle inutile? Je veux dire, est-ce la même chose que a = (int) b dans tous les cas?

Cela évite probablement un avertissement du compilateur sur les systèmes Unix 64 bits où unsigned long est une quantité de 64 bits et est donc suffisamment important pour contenir un pointeur, alors que int est une quantité de 32 bits insuffisante pour contenir un pointeur. Le transtypage sur (unsigned long) conserve tous les bits de l’adresse; la conversion ultérieure en int supprime les 32 bits d’ordre élevé de l’adresse, mais le fait sans avertissement par défaut.

Démontrer:

 int main(void) { void *b = (void *)0x12345678; int a = (int)(unsigned long)b; int c = (int)b; return a + c; } $ gcc -O3 -g -std=c99 -Wall -Wextra -c ar.c ar.c: In function 'main': ar.c:5:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] $ 

Utilisation de GCC 4.7.1 sur Mac OS X 10.8.4, par défaut pour la compilation 64 bits.

Il est intéressant de spéculer sur ce qui sera fait avec la valeur “partie d’une adresse”.

Le transtypage direct de type “pointeur vers un type plus petit” dit int peut entraîner une erreur de compilation sur certains compilateurs (comme Clang) dans un environnement x64 bits.

Par exemple:

  void *p = GetSomeAddress; int i = (int)p; //error on comstackrs like Clang. 

La solution est:

 int i = (int)(unsigned long)p; 

ou

 int i = (int)(long)p; 

En effet, sous Unix, sous le modèle LP64, long est 64 bits.

Dans de tels cas, vous devez examiner attentivement les raisons pour lesquelles vous avez besoin de la conversion de type de pointeur en type int ou autre, ce qui peut entraîner une perte des données.

Cette question peut aussi vous aider. Comment gérer “la conversion de” void * “vers” int “perd en précision” lors de la compilation de code 32 bits sur une machine 64 bits?

Je le vois aussi dans mon projet.

Pour mon cas, le contenu de “b” est rempli par d’autres sources / middleware utilisés pour la communication inter-processus.

Une fois que ‘b’ est rempli, le programme obtiendra le contenu de ‘b’ avec un transtypage dans le champ correct ‘a’. l’application utilise ensuite ‘a’ pour le traitement.

Mon projet utilise char * au lieu de void *.