Почему " sizeof (a? true: false) " дать выход из четырех байтов?


у меня есть небольшой кусок кода, о sizeof оператор с тернарным оператором:

#include <stdio.h>
#include <stdbool.h>

int main()
{
    bool a = true;
    printf("%zun", sizeof(bool));  // Ok
    printf("%zun", sizeof(a));     // Ok
    printf("%zun", sizeof(a ? true : false)); // Why 4?
    return 0;
}

выход (GCC):

1
1
4 // Why 4?

но здесь,

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

тернарный оператор возвращает boolean тип и sizeof bool тип 1 байт в C.

затем почему sizeof(a ? true : false) дать выход в четыре байта?

7 128

7 ответов:

это потому что у тебя #include <stdbool.h>. Этот заголовок определяет макросtrue и false на 1 и 0, так что ваше заявление выглядит так:

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

sizeof(int) 4 на вашей платформе.

вот, тернарный оператор return boolean тип,

хорошо, это еще не все!

В C, результат этой троичная операция имеет тип int. [ноты ниже (1,2)]

следовательно, результат такой же, как выражение sizeof(int), на вашей платформе.


Примечание 1: Цитировать C11 глава §7.18, Boolean type and values <stdbool.h>

[....] Остальные три макроса подходят для использования в #if директивы препроцессора. Они являются

true

который расширяется до целочисленной константы 1,

false

, который расширяется до целой константы 0, [....]

примечание 2: для условного оператора, глава §6.5.15, (выделено мной)

вычисляется первый операнд; есть точка последовательности между ее оценкой и оценка второго или третьего операнда (что оценивается). Второй операнд вычисляется только в том случае, если первый сравнивается неравным 0; третий операнд вычисляется только в том случае, если первый сравнивается равным 0;результатом является значение второго или третьего операнда (в зависимости от того, что оценивается), [...]

и

если второй и третий операнды арифметические тип, тип результата, который будет определяемые обычными арифметическими преобразованиями, применялись ли они к этим двум операндам, это тип результата. [....]

следовательно, результат будет иметь тип integer и из-за диапазона значений константы точно имеют тип int.

что сказал, общий совет,int main() лучше int main (void) чтобы быть по-настоящему стандарте.

тернарный оператор является отвлекающим маневром.

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

печатает 4 (или что угодно sizeof(int) это на вашей платформе).

здесь предполагается, что bool синоним char или аналогичный тип размера 1, и int больше, чем char.

почему sizeof(true) != sizeof(bool) и sizeof(true) == sizeof(int) просто так true и не выражения типа bool. Это выражение типа int. Это #defineд 1 in stdbool.h.

нет rvalues типа bool в C вообще. Каждое такое значение сразу же повышается до int, даже если используется в качестве аргумента для sizeof. Edit: этот абзац не соответствует действительности, аргументы для sizeof не произведен в int. Однако это не влияет ни на один из выводов.

относительно логического типа В C

логический тип был введен довольно поздно в языке C, в 1999 году. До этого C не имел логического типа, но вместо этого использовал int для всех логических выражений. Поэтому все логические операторы, такие как > == ! etc возвращает int стоимостью 1 или 0.

это было специально для приложений, чтобы использовать самодельные типы, такие как typedef enum { FALSE, TRUE } BOOL;, что также сводится к int-размер типы.

у C++ был гораздо лучший и явный логический тип,bool, который был не больше 1 байта. В то время как логические типы или выражения в C в худшем случае будут иметь размер 4 байта. Некоторый способ совместимости с C++ был введен в C со стандартом C99. Тогда C есть тип boolean _Bool, а также заголовок stdbool.h.

stdbool.h обеспечивает некоторую совместимость с C++. Этот заголовок определяет макрос bool (то же написание, что и ключевое слово C++), что расширяется до _Bool, тип, который является малым целочисленным типом, вероятно, 1 байт большой. Аналогично, заголовок предоставляет два макроса true и false, то же написание, что и ключевые слова C++,но с обратной совместимостью с более старыми программами C. Поэтому true и false расширить до 1 и 0 в C и их типа int. Эти макросы на самом деле не имеют логического типа, как соответствующие ключевые слова C++.

аналогично, для обратной в целях совместимости, логические операторы в C еще возвратить int по сей день, хотя C в настоящее время получил логический тип. В то время как в C++ логические операторы возвращают bool. Таким образом, выражение типа sizeof(a == b) даст размер int В C, но размер a bool в C++.

относительно условного оператора ?:

условный оператор ?: это странный оператор с парой причуд. Это распространенная ошибка считать, что это на 100% эквивалентно if() { } else {}. Не совсем.

точка следования между оценкой 1-го и 2-го или 3-го операнда. Элемент ?: оператор гарантированно оценивает только 2-й или 3-й операнд, поэтому он не может выполнять никаких побочных эффектов операнда, который не оценивается. Код типа true? func1() : func2() не будет выполнять func2(). Пока все идет хорошо.

, есть специальное правило, гласящее, что 2-й и 3-й операнд должны получить неявно тип повышен и сбалансированы друг против друга с обычные арифметические преобразования. (неявные правила продвижения типа В C объяснены здесь). Это означает, что 2-й или 3-й операнд будет всегда быть, по крайней мере, как большой, как int.

так что это не имеет значения true и false случилось быть типа int в C, потому что выражение всегда будет давать хоть размер int неважно.

даже если бы вы переписать выражение дляsizeof(a ? (bool)true : (bool)false)он все равно вернет размерint!

это связано с неявным продвижением типа через обычные арифметические преобразования.

короткий ответ:

  • sizeof(a ? true : false) оценивает в 4, потому что true и false определена в <stdbool.h> как 1 и 0 соответственно, поэтому выражение расширяется до sizeof(a ? 1 : 0) который является целочисленным выражением с типом int, который занимает 4 байта на вашей платформе. По той же причине, sizeof(true) также будет оценивать к 4 на вашей системе.
внимание:
  • sizeof(a ? a : a) также оценивает к 4 потому что тернарный оператор выполняет целочисленные продвижения по своим второму и третьему операндам, если это целочисленные выражения. То же происходит sizeof(a ? true : false) и sizeof(a ? (bool)true : (bool)false), но бросая все выражение как bool ведет себя так, как ожидалось:sizeof((bool)(a ? true : false)) -> 1.

  • также обратите внимание, что операторы сравнения вычисляют логические значения 1 или 0, но int тип: sizeof(a == a) -> 4.

только операторы, которые держат логического характера a будет:

  • оператор "запятая": обе sizeof(a, a) и sizeof(true, a) оценка для 1 во время компиляции.

  • операторы присваивания: обе sizeof(a = a) и sizeof(a = true) имеет значение 1.

  • операторы инкремента: sizeof(a++) -> 1

наконец, все вышесказанное относится только к C: C++ имеет разную семантику относительно bool тип, логические значения true и false, операторы сравнения и тернарный оператор: все это sizeof() выражений 1 в C++.

вот фрагмент, из которого состоит то, что включено в источник

#ifndef __cplusplus

#define bool    _Bool
#define true    1
#define false   0

#else /* __cplusplus */

есть макрос true и false объявляются как 1 и 0 соответственно.

в этом случае тип является типом символьных констант. И 0, и 1 являются целочисленными константами, которые вписываются в int, поэтому их тип-int.

и sizeof(int) в вашем случае это 4.

в C нет логического типа данных, вместо логических выражений вычисляются целочисленные значения 1 когда true в противном случае 0.

условные выражения, как if,for,while или c ? a : b ожидайте целое число, если число не равно нулю, оно считается true за исключением некоторых особых случаев, Вот рекурсивная функция суммы, в которой тернарный оператор будет оценивать true до n reach 0.

int sum (int n) { return n ? n+sum(n-1) : n ;

его можно также использовать к NULL проверьте указатель, вот рекурсивная функция, которая печатает содержимое односвязного списка.

void print(sll * n){ printf("%d -> ",n->val); if(n->next)print(n->next); }