У меня есть небольшой фрагмент кода об sizeof
операторе с троичным оператором:
#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;
}
Выход ( GCC ):
1
1
4 // Why 4?
Но здесь,
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
троичный оператор возвращает boolean
тип, а sizeof bool
является 1
байтом в C.
Тогда почему sizeof(a ? true : false)
выдается четыре байта?
sizeof(true)
аsizeof(false)
также 4: ide.geeksforgeeks.org/O5jvuN_Bool
размер 1, но не «true
и»false
. Но стандарту нечего сказать об этом, насколько я могу судить.char a;
sizeof(a) == 1
иsizeof('a') == sizeof(int)
(на С). Дело не в реализации, а в языке.sizeof(true)
? возможно, это прояснит ситуацию (в частности, станет очевидным, что троичный оператор - красная сельдь).true
есть#define
д , чтобы быть 1 с помощьюstdbool.h
да так, что это определение буквальным.Ответы:
Это потому что у тебя есть
#include <stdbool.h>
. Этот заголовок определяет макросыtrue
иfalse
быть1
и0
, поэтому ваше утверждение выглядит следующим образом:sizeof(int)
4 на вашей платформе.источник
sizeof(a ? (uint8_t)1 : (uint8_t)0);
также даст результат 4.?:
Важной частью здесь является целочисленное продвижение операндов, а не размерtrue
иfalse
.int
без продвижения. Причина, по которой вы не можете «исправить», - это продвижение по умолчанию.true
и неfalse
являются макросами; они являются ключевыми словами. Они не определены как и , но как истинные и ложные значения типа.1
0
bool
sizeof(true)
есть 1. Демо .ОК, это еще не все!
В С результат этой троичной операции имеет тип
int
. [примечания ниже (1,2)]Следовательно, результат совпадает с выражением
sizeof(int)
на вашей платформе.Примечание 1: Цитирование
C11
, глава §7.18,Boolean type and values <stdbool.h>
Примечание 2: Для условного оператора, глава §6.5.15, ( выделено мной )
и
следовательно, результат будет целочисленным, а из-за диапазона значений константы имеют тип
int
.Тем не менее, общий совет
int main()
должен быть лучшеint main (void)
соответствовать стандартам.источник
<stdbool.h>
определяет MACROS для типаint
.. это что-то не так?Тройной оператор - красная сельдь.
печатает 4 (или что-нибудь
sizeof(int)
на вашей платформе).Далее предполагается, что
bool
это синонимchar
или аналогичный тип размера 1 иint
больше, чемchar
.Причина , почему
sizeof(true) != sizeof(bool)
иsizeof(true) == sizeof(int)
просто потому , чтоtrue
это не выражение типаbool
. Это выражение типаint
. Это#define
как1
вstdbool.h
.Нет никаких значений типаИзменить: этот абзац не соответствует действительности, аргументы, которыеbool
в C вообще. Каждому такому значению сразу присваивается значениеint
, даже если оно используется в качестве аргументаsizeof
.sizeof
не будут выдвинутыint
. Это не влияет ни на один из выводов, хотя.источник
(bool)1
тип значенияbool
?printf("%u\n", sizeof((char) 1));
печатает1
на моей платформе, тогда какprintf("%u\n", sizeof(1));
печатает4
. Не означает ли это, что ваше утверждение «Каждое такое значение сразу переводится в int, даже если оно используется в качестве аргумента для sizeof», является ложным?true
т. Д. На самом деле не имеет значения в случае,?:
так как в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 получил логический тип,_Bool
а также заголовокstdbool.h
.stdbool.h
обеспечивает некоторую совместимость с C ++. Этот заголовок определяет макросbool
(то же самое, что и ключевое слово C ++), который расширяется до_Bool
типа, представляющего собой небольшой целочисленный тип, вероятно, размером 1 байт. Точно так же заголовок обеспечивает два макросаtrue
и тоfalse
же самое написание, что и ключевые слова C ++, но с обратной совместимостью со старыми программами на Си . Поэтомуtrue
иfalse
расширяются до1
и0
в С и их тип естьint
. Эти макросы на самом деле не имеют логического типа, как соответствующие ключевые слова C ++.Точно так же в целях обратной совместимости логические операторы в C все еще возвращают значение
int
по сей день, хотя C в настоящее время получил логический тип. В то время как в C ++ логические операторы возвращаютbool
. Таким образом, выражение, такое какsizeof(a == b)
даст размерint
в C, но размер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(bool)==1
.Быстрый ответ:
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 ++.источник
true
иfalse
есть, потому что?:
операнды вint
любом случае получат целое число . Таким образомsizeof(a ? (uint8_t)true : (uint8_t)false)
, также даст 4 как результат.int
Вот фрагмент из того, что входит в источник
Там макросы
true
иfalse
объявляются как 1 и 0 соответственно.однако в этом случае тип является типом литеральных констант. И 0, и 1 являются целочисленными константами, которые помещаются в int, поэтому их тип - int.
и
sizeof(int)
в вашем случае это 4.источник
В C нет логического типа данных, вместо этого логические выражения оцениваются как целочисленные значения,
1
если в противном случае они имеют значение true0
.Условные выражения , как
if
,for
,while
илиc ? a : b
ожидать целое число, если число не равно нулю это считаетсяtrue
за исключением некоторых особых случаев, вот рекурсивная функция суммы , в которой тройной-оператор будет оцениватьtrue
доn
досягаемости0
.Он также может быть использован для
NULL
проверки указателя, вот рекурсивная функция, которая печатает содержимое односвязного списка.источник