139 votes

Pourquoi "sizeof (a? True: false)" donne-t-il une sortie de quatre octets?

J'ai un petit morceau de code sur l' sizeof de l'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;
}

De sortie (GCC):

1
1
4 // Why 4?

Mais ici,

printf("%zu\n", sizeof(a ? true : false)); // Why 4?

l'opérateur ternaire retours boolean type et sizeof bool type 1 octet en C.

Alors pourquoi est - sizeof(a ? true : false) donnera une sortie de quatre octets?

226voto

Quincunx Points 1923

C'est parce que vous avez #include <stdbool.h> . Cet en-tête définit les macros true et false comme 1 et 0 , de sorte que votre énoncé se présente comme suit:

 printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4?
 

sizeof(int) est 4 sur votre plate-forme.

68voto

Sourav Ghosh Points 54713

Ici, opérateur ternaire retour boolean type,

OK, il y a plus de pour que!

En C, le résultat de cette opération ternaire est de type int. [note ci-dessous (1,2)]

Donc le résultat est le même que l'expression sizeof(int), sur votre plate-forme.


Note 1: en Citant C11, au chapitre §7.18, Boolean type and values <stdbool.h>

[....] Les trois autres macros sont adaptés pour une utilisation en #if de prétraitement des directives. Ils sont

true

qui s'étend à l'entier de la constante 1,

false

qui s'étend à l'entier de la constante 0, [....]

Remarque 2: Pour l'opérateur conditionnel, au chapitre §6.5.15, (c'est moi qui souligne)

Le premier opérande est évalué; il y a un point de séquence entre son évaluation et le évaluation de la deuxième ou de la troisième opérande (celui qui est évalué). Le deuxième opérande est évaluée uniquement si le compare d'abord l'inégalité à 0; le troisième opérande est évaluée uniquement si la première compare égal à 0; le résultat est la valeur de la deuxième ou de la troisième opérande (celui qui est évalué), [...]

et

Si les deuxième et troisième opérandes ont arithmétique de type, le type de résultat qui serait déterminé par l'habitude de l'arithmétique des conversions, ont-ils été appliqué à ces deux opérandes, est le type du résultat. [....]

par conséquent, le résultat sera de type entier et en raison de la gamme de valeur, les constantes sont précisément de type int.

Cela dit, les conseils généraux, int main() devraient être mieux int main (void) pour être vraiment standard conforme.

60voto

n.m. Points 30344

L'opérateur ternaire est un leurre.

    printf("%zu\n", sizeof(true));

tirages de 4 (ou de ce qu' sizeof(int) sur votre plate-forme).

Ce qui suit suppose que bool est un synonyme char ou d'un type similaire de taille 1, et int est plus grand que char.

La raison pourquoi sizeof(true) != sizeof(bool) et sizeof(true) == sizeof(int) est tout simplement parce qu' true est pas une expression de type bool. C'est une expression de type int. C'est - #defined en 1 en stdbool.h.

Il n'y a pas rvalues de type bool dans C à tous. Tous ces rvalue est immédiatement promu int, même lorsqu'il est utilisé comme un argument à l' sizeof. Edit: ce paragraphe n'est pas vrai, arguments au sizeof n'obtenez pas promu int. Cela ne veut pas avoir d'incidence sur les conclusions de bien.

33voto

Lundin Points 21616

Concernant le type booléen en C

Un type booléen a été introduit assez tard dans le langage C, en l'an 1999. Avant, C n'ont pas de type booléen, mais plutôt utilisé int pour l'ensemble des expressions booléennes. Par conséquent, tous les opérateurs logiques tels que > == ! etc retourner un int de la valeur 1 ou 0.

C'était la coutume pour les applications à utiliser à la maison-faites des types tels que typedef enum { FALSE, TRUE } BOOL;, aussi, qui se résume à de la int-taille des types.

C++ est beaucoup mieux, et explicite de type booléen, bool, ce qui n'était pas plus grand que 1 octet. Alors que le booléen types ou des expressions en C constituerait 4 octets dans le pire des cas. D'une certaine manière, de la compatibilité avec le C++ a été introduit en C avec le standard C99. C puis a obtenu un type booléen _Bool et aussi l'en-tête stdbool.h.

stdbool.h fournit une certaine compatibilité avec le C++. Cet en-tête définit la macro bool (même orthographe que C++ mot-clé) qui s'étend à l' _Bool, un type qui est un entier plus petit type, probablement 1 octet grand. De même, l'en-tête fournit deux macros true et false, même orthographe que C++ mots-clés, mais avec compatibilité descendante pour les plus âgés C programmes. Par conséquent, true et false étendre à d' 1 et 0 en C et leur type est int. Ces macros ne sont pas réellement de type booléen comme le C++ correspondante mots clés serait.

De même, pour des raisons de compatibilité descendante, les opérateurs logiques en C encore retour une int à ce jour, même si C de nos jours a un type booléen. Alors qu'en C++, les opérateurs logiques retour un bool. Ainsi, une expression telle que sizeof(a == b) donnera la taille d'un int de C, mais de la taille d'un bool en C++.

Quant à l'opérateur conditionnel ?:

L'opérateur conditionnel ?: est bizarre opérateur avec un couple de bizarreries. C'est une erreur commune de croire que c'est 100% équivalent à if() { } else {}. Pas tout à fait.

Il y a un point de séquence entre l'évaluation de la 1ère et de la 2ème ou 3ème d'opérande. L' ?: de l'opérateur est garantie uniquement à évaluer le 2ème ou le 3ème opérateur, de sorte qu'il ne peut pas s'exécuter tous les effets secondaires de l'opérande qui n'est pas évalué. Code comme celui - true? func1() : func2() de ne pas exécuter func2(). Pour l'instant, donc bon.

Cependant, il existe une règle spéciale indiquant que le 2e et le 3e opérande doit obtenir implicitement type promu et mis en balance avec l' habitude de l'arithmétique des conversions. (Implicite des règles de promotion de type C expliqué ici). Cela signifie que la 2ème ou 3ème opérande va toujours être au moins aussi grand que l' int.

Donc, il n'est pas question qu' true et false se trouvent être de type int C parce que l'expression serait toujours donner au moins la taille d'un int , peu importe.

Même si vous voulez réécrire l'expression d' sizeof(a ? (bool)true : (bool)false) il serait encore de retour de la taille d'un int !

C'est à cause de type implicites de la promotion par le biais d'habitude arithmétique des conversions.

23voto

chqrlie Points 17105

Réponse rapide:

  • sizeof(a ? true : false) évalue 4 car true et false sont définies en <stdbool.h> comme 1 et 0 , respectivement, de sorte que l'expression s'étend à d' sizeof(a ? 1 : 0) qui est une expression entière avec le type int, qui occupe 4 octets sur votre plate-forme. Pour la même raison, sizeof(true) permettrait aussi d'évaluer d' 4 sur votre système.

À noter toutefois que:

  • sizeof(a ? a : a) évalue aussi pour 4 parce que l'opérateur ternaire effectue l'entier des promotions sur ses deuxième et troisième opérandes si ces sont des entiers expressions. La même chose se passe pour sizeof(a ? true : false) et sizeof(a ? (bool)true : (bool)false), mais la coulée de l'ensemble de l'expression en tant que bool se comporte comme prévu: sizeof((bool)(a ? true : false)) -> 1.

  • notez également que les opérateurs de comparaison pour évaluer les valeurs booléennes 1 ou 0, mais avez - int type: sizeof(a == a) -> 4.

Les seuls opérateurs qui gardent le booléen de la nature de l' a serait:

  • l'opérateur virgule: les deux sizeof(a, a) et sizeof(true, a) évaluer à l' 1 au moment de la compilation.

  • les opérateurs d'affectation: les deux sizeof(a = a) et sizeof(a = true) ont une valeur de 1.

  • les opérateurs d'incrémentation: sizeof(a++) -> 1

Enfin, l'ensemble de la ci-dessus s'applique à C uniquement: C++ dispose de différents sémantique concernant l' bool type, les valeurs booléennes true et false, les opérateurs de comparaison et l'opérateur ternaire: tous ces sizeof() expressions sont évaluées à 1 en C++.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X