Interprétation C du littéral entier long «H» hexadécimal

Comment un compilateur C interprète-t-il le “L” qui désigne un littéral entier long, à la lumière d’une conversion automatique? Le code suivant, lorsqu’il est exécuté sur une plate-forme 32 bits (long de 32 bits, long de 64 bits), semble convertir l’expression “(0xffffffffL)” dans l’entier 64 bits 4294967295, et non 32 bits -1.

Exemple de code:

#include  int main(void) { long long x = 10; long long y = (0xffffffffL); long long z = (long)(0xffffffffL); printf("long long x == %lld\n", x); printf("long long y == %lld\n", y); printf("long long z == %lld\n", z); printf("0xffffffffL == %ld\n", 0xffffffffL); if (x > (long)(0xffffffffL)) printf("x > (long)(0xffffffffL)\n"); else printf("x  (0xffffffffL)) printf("x > (0xffffffffL)\n"); else printf("x <= (0xffffffffL)\n"); return 0; } 

Sortie (compilé avec GCC 4.5.3 sur une Debian 32 bits):

 long long x == 10 long long y == 4294967295 long long z == -1 0xffffffffL == -1 x > (long)(0xffffffffL) x <= (0xffffffffL) 

C’est un littéral hexadécimal, donc son type peut être non signé. Il tient dans unsigned long , c’est donc le type qu’il obtient. Voir la section 6.4.4.1 de la norme:

Le type d’une constante entière est le premier de la liste correspondante dans laquelle sa valeur peut être représentée.

où la liste des littéraux hexadécimaux avec le suffixe L est

  1. long
  2. unsigned long
  3. long long
  4. unsigned long long

Comme il ne convient pas à une long signature 32 bits, mais à une long non signée 32 bits, c’est ce que cela devient.

Le fait est que les règles pour déterminer le type du littéral intégral sont différentes selon que vous avez un nombre décimal ou un nombre hexadécimal (ou un nombre octal). Un littéral décimal est toujours signé à moins que postfixes avec U. Un littéral hexadécimal ou octal peut également être non signé si le type signé ne peut pas contenir la valeur.