quelle est la raison de déclarer explicitement L ou UL pour les valeurs longues
À partir d'un Exemple
unsigned long x = 12345678UL
Nous ont toujours appris que le compilateur a besoin de voir que des "long" dans l'exemple ci-dessus pour définir les 4 octets (32 bits) de mémoire. La question est de savoir pourquoi devrions-nous utiliser L/UL au long des constantes même après avoir déclaré qu'elle sera longue.
- Voulez-vous dire pourquoi
UL
est utilisé à la place deL
ou au lieu de rien? - Pas de. Pourquoi devons-nous utiliser L/UL en valeurs longues.
- Cette question est pour C. Cette question est pour le C++ et l'on a accepté la réponse est à propos de la surcharge. Ce n'est pas un doublon de cette.
- Pascal est correcte, cette question n'est pas un doublon de la question. Nomination pour le rouvrir.
Vous devez vous connecter pour publier un commentaire.
Lorsqu'un suffixe
L
ouUL
n'est pas utilisé, le compilateur utilise le premier type, qui peuvent contenir des constantes à partir d'une liste (voir les détails dans le standard C99, l'article 6.4.4:5. Pour une virgule constante, la liste estint
,long int
,long long int
).En conséquence, la plupart du temps, il n'est pas nécessaire d'utiliser le suffixe. Il ne change pas le sens du programme. Il ne change pas le sens de votre exemple d'initialisation de
x
pour la plupart des architectures, bien qu'il aurait fait si vous aviez choisi un nombre qui ne peut pas être représenté comme unelong long
. Voir aussi codebauer de réponse pour un exemple où l'U
partie du suffixe est nécessaire.Il ya un couple de circonstances lorsque le programmeur peut définir le type de la constante de manière explicite. Un exemple est lorsque vous utilisez un variadic fonction:
Un motif fréquent d'utiliser un suffixe est de s'assurer que le résultat d'un calcul ne déborde pas. Deux exemples sont:
Dans les deux exemples, sans les suffixes, les constantes auraient type
int
et le calcul serait effectué queint
. Dans chaque exemple, cela engendre un risque de débordement. En utilisant les suffixes signifie que le calcul sera fait dans un plus grand type à la place, qui a une portée suffisante pour le résultat.Que la Légèreté des Courses en Orbite le met, le littérale du suffixe vient avant la cession. Dans les deux exemples ci-dessus, le simple fait de déclarer
x
commelong
ety
commeunsigned long long
n'est pas suffisant pour empêcher le débordement dans le calcul des expressions attribuées.Un autre exemple est la comparaison
x < 12U
où la variablex
a typeint
. Sans leU
suffixe, le compilateur types de la constante12
comme unint
, et la comparaison est donc une comparaison de signé ints.Avec le
U
suffixe, la comparaison devient une comparaison des entiers non signés. “D'habitude arithmétique des conversions” signifient que -3 est converti à un grand unsigned int:En effet, le type d'une constante peut même changer le résultat d'un calcul arithmétique, de nouveau en raison de la manière “habituelle arithmétique des conversions de travail.
Noter que, pour les décimales de constantes, de la liste des types suggéré par C99 ne contient pas de
unsigned long long
. En C90, la liste est terminée avec la plus grande normalisée de type entier non signé à l'époque (qui étaitunsigned long
). Une conséquence en est que le sens de certains programmes a été modifié par adjonction de la norme de typelong long
à C99: la même constante qui a été tapé commeunsigned long
en C90 pourrait maintenant être tapé comme un signélong long
à la place. Je crois que c'est la raison pour laquelle en C99, il a été décidé de ne pas avoirunsigned long long
dans la liste des types pour les décimales des constantes.Voir cette et cette messages de blog pour un exemple.
#define MY_DEFINE 123456789UL
et que vous utilisezMY_DEFINE
plus tard dans le code. Naturellement, il n'a pas de type associé avec elleUL
plus peut-être de peu d'aide ici.18446744073709551615
est traitée comme-1L
sur les systèmes avec une version 64 bitslong
. Vous devez utiliser explicitementUL
.1 << 36
est probablement UB,1ULL << 36
est sûr. Peut-être la peine d'être ajouté à la liste d'exemples.*_C
macros dansstdint.h
dans cette réponse ainsi. C'est déjà assez détaillé 😉 E. g.UINT64_C(x)
produit une littérale de la valeur de x avec le droit suffixe de faire son typeuint64_t
- donc il n'est pas nécessaire pour les préfixes spécifiques pour lastdint.h
types de données._C
macro. Merci pour votre commentaire.2147483648
n'est pas unint
4294967299*2
est bien défini l'expression, de typelong
oulong long
(long
silong
est en 64 bits). D'autre part2000000000*3
est une expression de typeint
qui contient un comportement indéfini, parce que2000000000
est typé commeint
et la multiplication des débordements. C'est une drôle de langue.Parce que les littéraux numériques sont typiquement de type int. L'UL/L indique au compilateur qu'ils ne sont pas de type int, par exemple, en supposant que les 32 bits de type int et 64 bits de long
Ici les valeurs du droit doit être converti pour les longs signés (32bit -> 64bit)
0xffff
est unint
avec la valeur de 65 535. L'affectation que pouri
n'est pas un problème.0xffffUL
est ununsigned long
avec la valeur de 65 535. L'affectation que pourj
est également pas un problème. A cet exemple étélong i = 0xffffffff;
0xffffffff
est ununsigned
avec la valeur de 4,294,967,295 et l'affectation que pour 64-long
n'est pas un problème. Aussi un non-problème aveclong j = 0xffffffffUL;
Cette réponse #1 "converti en long à l'aide de l'extension du signe" n'est pas le cas ici.Car il n'est pas "après", c'est "avant".
D'abord vous avez le sens littéral, puis il est converti quel que soit le type de la variable que vous essayez de serrer dans.
Liées à ce poste est pourquoi un
u
.Une raison pour
u
est de permettre à un constante entière plus deLLONG_MAX
sous la forme décimale.