J'ai un petit morceau de code sur l' sizeof
opérateur avec l'opérateur ternaire:
#include <stdio.h>
#include <stdbool.h>
int main()
{
bool a = true;
printf("%zu\n", sizeof(bool)); // Ok
printf("%zu\n", sizeof(a)); // Ok
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
return 0;
}
Sortie ( GCC ):
1
1
4 // Why 4?
Mais ici,
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
l'opérateur ternaire renvoie le boolean
type et la taille du bool
type est l' 1
octet en C.
Alors pourquoi sizeof(a ? true : false)
donne-t-il une sortie de quatre octets?
sizeof(true)
etsizeof(false)
c'est aussi 4: ide.geeksforgeeks.org/O5jvuN_Bool
taille 1, mais pastrue
etfalse
. Mais la norme n'a rien à dire à ce sujet pour autant que je sache.char a;
sizeof(a) == 1
etsizeof('a') == sizeof(int)
(en C). Il ne s'agit pas de la mise en œuvre, mais de la langue.sizeof(true)
? peut-être que cela rendra les minces un peu plus claires (en particulier, il deviendra évident que l'opérateur ternaire est un hareng rouge).true
est#define
d être égal à 1,stdbool.h
donc oui, c'est la définition littérale.Réponses:
C'est parce que vous avez
#include <stdbool.h>
. Cet en-tête définit les macrostrue
etfalse
être1
et0
, donc votre déclaration ressemble à ceci:sizeof(int)
est 4 sur votre plateforme.la source
sizeof(a ? (uint8_t)1 : (uint8_t)0);
donnerait également un résultat de 4. La promotion entière des?:
opérandes est la partie importante ici, pas la taille detrue
etfalse
.int
sans promotion. La raison pour laquelle vous ne pouvez pas "réparer" ce sont les promotions par défaut.true
et nefalse
sont pas des macros; ce sont des mots clés. Ils ne sont pas définis pour être1
et0
, mais pour être les valeurs vraie et fausse dubool
type.sizeof(true)
est 1. démo .OK, il y a plus à ça!
En C, le résultat de cette opération ternaire est de type
int
. [notes ci-dessous (1, 2)]Par conséquent, le résultat est le même que l'expression
sizeof(int)
, sur votre plateforme.Note 1:
C11
Citations, chapitre §7.18,Boolean type and values <stdbool.h>
Note 2: Pour l'opérateur conditionnel, chapitre §6.5.15, (c'est moi qui souligne )
et
par conséquent, le résultat sera de type entier et en raison de la plage de valeurs, les constantes sont précisément de type
int
.Cela dit, un conseil générique
int main()
devrait êtreint main (void)
d'être vraiment conforme aux normes.la source
<stdbool.h>
définit les MACROS comme étant de typeint
... est-ce faux?L'opérateur ternaire est un hareng rouge.
imprime 4 (ou ce qui se
sizeof(int)
trouve sur votre plate-forme).Ce qui suit suppose qu'il
bool
s'agit d'un synonyme dechar
ou d'un type similaire de taille 1 et qu'ilint
est supérieur àchar
.La raison pour laquelle
sizeof(true) != sizeof(bool)
etsizeof(true) == sizeof(int)
est simplement parce quetrue
n'est pas une expression de typebool
. C'est une expression de typeint
. C'est#define
d comme1
dansstdbool.h
.Il n'y a pas du tout de valeurs de typeEdit: ce paragraphe n'est pas vrai, arguments pourbool
en C. Chaque rvalue de ce type est immédiatement promue versint
, même lorsqu'elle est utilisée comme argument desizeof
.sizeof
ne pas être promuint
. Cela n'affecte cependant aucune des conclusions.la source
(bool)1
rvalue n'est-elle pas de typebool
?printf("%u\n", sizeof((char) 1));
imprime1
sur ma plate-forme tandis queprintf("%u\n", sizeof(1));
imprime4
. Cela ne signifie-t-il pas que votre déclaration "Chaque rvalue est immédiatement promue en int, même lorsqu'elle est utilisée comme argument de sizeof" est fausse?true
etc n'a pas vraiment d'importance dans le cas de?:
car il obtient deint
toute façon un entier promu . Autrement dit, la réponse devrait expliquer pourquoi?:
est un hareng rouge.Concernant le type booléen en C
Un type booléen a été introduit assez tardivement dans le langage C, en 1999. Auparavant, C n'avait pas de type booléen mais était plutôt utilisé
int
pour toutes les expressions booléennes. Par conséquent, tous les opérateurs logiques tels que> == !
etc renvoient uneint
valeur1
ou0
.Il était habituel pour les applications d'utiliser des types faits maison tels que
typedef enum { FALSE, TRUE } BOOL;
, qui se résume également à desint
types de taille réduite.C ++ avait un type booléen bien meilleur et explicite
bool
, qui ne dépassait pas 1 octet. Alors que les types ou expressions booléens en C finiraient par 4 octets dans le pire des cas. Une certaine compatibilité avec C ++ a été introduite en C avec la norme C99. C a alors obtenu un type booléen_Bool
et également l'en-têtestdbool.h
.stdbool.h
fournit une certaine compatibilité avec C ++. Cet en-tête définit la macrobool
(même orthographe que le mot clé C ++) qui se développe en_Bool
, un type qui est un petit type entier, probablement 1 octet de large. De même, l'en-tête fournit deux macrostrue
et lafalse
même orthographe que les mots-clés C ++, mais avec une compatibilité descendante avec les programmes C plus anciens . Par conséquent,true
etfalse
développez vers1
et0
dans C et leur type estint
. Ces macros ne sont pas réellement de type booléen comme le seraient les mots-clés C ++ correspondants.De même, à des fins de compatibilité ascendante, les opérateurs logiques en C renvoient toujours un
int
à ce jour, même si C de nos jours a un type booléen. En C ++, les opérateurs logiques renvoient unbool
. Ainsi, une expression telle quesizeof(a == b)
donnera la taille d'unint
en C, mais la taille d'unbool
en C ++.Concernant l'opérateur conditionnel
?:
L'opérateur conditionnel
?:
est un opérateur étrange avec quelques bizarreries. C'est une erreur courante de croire que cela équivaut à 100%if() { } else {}
. Pas assez.Il y a un point de séquence entre l'évaluation du 1er et du 2ème ou 3ème opérande. Il
?:
est garanti que l'opérateur n'évalue que le 2ème ou le 3ème opérande, il ne peut donc exécuter aucun effet secondaire de l'opérande qui n'est pas évalué. Le code commetrue? func1() : func2()
ne s'exécutera pasfunc2()
. Jusqu'ici tout va bien.Cependant , il existe une règle spéciale indiquant que les 2ème et 3ème opérandes doivent être implicitement promus et équilibrés les uns par rapport aux autres avec les conversions arithmétiques habituelles . ( Les règles de promotion de type implicite en C expliquées ici ). Cela signifie que le 2ème ou 3ème opérande sera toujours au moins aussi grand qu'un
int
.Donc cela n'a pas d'importance
true
etfalse
il se trouve qu'il est de typeint
en C parce que l'expression donnerait toujours au moins la taille d'unint
peu importe.Même si vous réécriviez l'expression, elle renverrait toujours la taille d'un !
sizeof(a ? (bool)true : (bool)false)
int
Cela est dû à la promotion de type implicite via les conversions arithmétiques habituelles.
la source
sizeof(bool)==1
.Réponse rapide:
sizeof(a ? true : false)
s'évalue à4
parce quetrue
etfalse
sont définis respectivement dans<stdbool.h>
as1
et0
, donc l'expression se développe ensizeof(a ? 1 : 0)
une expression entière de typeint
, qui occupe 4 octets sur votre plate-forme. Pour la même raison,sizeof(true)
serait également évalué4
sur votre système.Notez cependant que:
sizeof(a ? a : a)
évalue également à4
parce que l'opérateur ternaire effectue les promotions d'entiers sur ses deuxième et troisième opérandes s'il s'agit d'expressions d'entiers. La même chose se produit bien sûr poursizeof(a ? true : false)
etsizeof(a ? (bool)true : (bool)false)
, mais jetant toute expressionbool
se comporte comme prévu:sizeof((bool)(a ? true : false)) -> 1
.noter également que les opérateurs de comparaison évaluer les valeurs booléennes
1
ou0
, mais ont leint
type:sizeof(a == a) -> 4
.Les seuls opérateurs qui conservent la nature booléenne de
a
seraient:l'opérateur virgule: les deux
sizeof(a, a)
etsizeof(true, a)
évaluer à1
au moment de la compilation.les opérateurs d'affectation: les deux
sizeof(a = a)
etsizeof(a = true)
ont une valeur de1
.les opérateurs d'incrémentation:
sizeof(a++) -> 1
Enfin, tout ce qui précède s'applique uniquement à C: C ++ a une sémantique différente concernant le
bool
type, les valeurs booléennestrue
etfalse
, les opérateurs de comparaison et l'opérateur ternaire: toutes cessizeof()
expressions sont évaluées1
en C ++.la source
true
et le type importent peufalse
, car les?:
opérandes obtiendraient deint
toute façon un entier promu . Ainsisizeof(a ? (uint8_t)true : (uint8_t)false)
donnera également 4 comme résultat.int
Voici un extrait de ce qui est inclus dans la source
Il y a des macros
true
etfalse
sont déclarés comme 1 et 0 respectivement.cependant, dans ce cas, le type est le type des constantes littérales. Les deux 0 et 1 sont des constantes entières qui tiennent dans un int, leur type est donc int.
et le
sizeof(int)
dans votre cas est 4.la source
Il n'y a pas de type de données booléen en C, à la place les expressions logiques s'évaluent à des valeurs entières
1
quand elles sont vraies sinon0
.Les expressions conditionnelles aiment
if
,for
,while
ouc ? a : b
attendre un entier, si le nombre est qu'il est non nul considéré ,true
sauf pour certains cas particuliers, voici une fonction somme récurrente dans laquelle l'opérateur ternaire évalueratrue
jusqu'àn
portée0
.Il peut également être utilisé pour
NULL
vérifier un pointeur, voici une fonction récursive qui imprime le contenu d'une liste à lien unique.la source