Почему " 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 ответов:
это потому что у тебя
#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д1instdbool.h.
нет rvalues типаEdit: этот абзац не соответствует действительности, аргументы дляboolв C вообще. Каждое такое значение сразу же повышается доint, даже если используется в качестве аргумента дляsizeof.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, но размер aboolв 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 */есть макрос
в этом случае тип является типом символьных констант. И 0, и 1 являются целочисленными константами, которые вписываются в int, поэтому их тип-int.trueиfalseобъявляются как 1 и 0 соответственно.и
sizeof(int)в вашем случае это 4.
в C нет логического типа данных, вместо логических выражений вычисляются целочисленные значения
1когда true в противном случае0.условные выражения, как
if,for,whileилиc ? a : bожидайте целое число, если число не равно нулю, оно считаетсяtrueза исключением некоторых особых случаев, Вот рекурсивная функция суммы, в которой тернарный оператор будет оцениватьtrueдоnreach0.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); }