Почему " 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
д1
instdbool.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
доn
reach0
.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); }