web-dev-qa-db-fra.com

Cast int to pointer - pourquoi cast to long first? (comme dans p = (void *) 42;)

Dans la documentation GLib , il y a un chapitre sur les macros de conversion de type. Dans la discussion sur la conversion d'un int en *void pointeur dit (accentuez le mien):

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 faire ceci:

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

(source: GLib Reference Manual for GLib 2.39.92, chapter Type Conversion Macros ).

Pourquoi cette conversion en long est-elle nécessaire?

Un élargissement requis de int ne devrait-il pas se produire automatiquement dans le cadre de la conversion en un pointeur?

15
sleske

Comme selon le C99: 6.3.2.3 citation:

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 d'interruption.56)

6 Tout type de pointeur peut être converti en 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 n'est pas défini. Le résultat n'a pas besoin d'être dans la plage de valeurs de n'importe quel type entier.

Selon la documentation du lien vous avez mentionné:

Les pointeurs ont toujours une taille d'au moins 32 bits (sur toutes les plateformes que GLib a l'intention de prendre en charge). Ainsi, vous pouvez stocker des valeurs entières d'au moins 32 bits dans une valeur de pointeur.

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

Donc, 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 uniquement, comme annoncé par GLib.

10
askmish

Je pense que c'est parce que cette conversion dépend de l'implémentation. Il vaut mieux utiliser uintptr_t à cet effet, car il est de la taille du type pointeur dans l'implémentation particulière.

2
DoctorMoisha