Cast int pour pointeur – pourquoi lancer long en premier? (comme dans p = (vide *) 42;)

La documentation de GLib contient un chapitre sur les macros de conversion de type. Dans la discussion sur la conversion d’un int en un pointeur *void il est dit (emphase mienne):

Naïvement, vous pouvez essayer ceci, mais c’est incorrect:

 gpointer p; int i; p = (void*) 42; i = (int) p; 

Encore une fois, cet exemple n’était pas correct, ne le copiez pas. Le problème est que sur certains systèmes, vous devez procéder comme suit:

 gpointer p; int i; p = (void*) (long) 42; i = (int) (long) p; 

(source: Manuel de référence GLib pour 2.38.92 GLib, chapitre Macros de conversion de type ).

Pourquoi cela est- long nécessaire long ?

L’élargissement requirejs de l’ int ne devrait-il pas se produire automatiquement dans le cadre de la conversion en un pointeur?

Selon la citation C99: 6.3.2.3 :

5 Un entier peut être converti en n’importe quel type de pointeur. Sauf indication contraire, le résultat est défini par l’implémentation, peut ne pas être correctement aligné, peut ne pas pointer vers une entité du type référencé et peut être une représentation de trappe.56)

6 Tout type de pointeur peut être converti en un type entier. Sauf indication contraire, le résultat est défini par l’implémentation. Si le résultat ne peut pas être représenté dans le type entier, le comportement est indéfini. Le résultat ne doit pas forcément être compris dans la plage de valeurs d’un type entier.

Selon la documentation sur le lien que vous avez mentionné:

Les pointeurs ont toujours une taille d’au moins 32 bits (sur toutes les plates-formes que GLib a l’intention de prendre en charge). Ainsi, vous pouvez stocker au moins 32 bits dans une valeur de pointeur.

Et plus long est garanti d’être au moins 32 bits .

Alors, le code

 gpointer p; int i; p = (void*) (long) 42; i = (int) (long) p; 

est plus sûr, plus portable et bien défini pour les entiers jusqu’à 32 bits, comme annoncé par GLib.

Je pense que c’est parce que cette conversion dépend de l’implémentation. Il est préférable d’utiliser uintptr_t à cette fin, car il s’agit exactement d’un type de pointeur dans une implémentation particulière.