Dlaczego " sizeof (a? true: false) " daje wyjście o 4 bajty?
Mam mały fragment kodu o operatorze sizeof
z operatorem trójdzielnym:
#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;
}
Output (GCC):
1
1
4 // Why 4?
Ale tutaj,
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
Operator trójdzielny zwraca boolean
type I sizeof bool
type jest 1
bajtem w C.
To dlaczego sizeof(a ? true : false)
daje wyjście o czterech bajtach?
7 answers
To dlatego, że masz #include <stdbool.h>
. Ten nagłówek definiuje makra true
i false
być 1
i 0
, więc Twoje stwierdzenie wygląda tak:
printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4?
sizeof(int)
jest 4 na platformie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-30 08:42:46
tutaj, operator trójdzielny return
boolean
type,
OK, to coś więcej!
W C, wynik to operacja trójwarstwowa jest typu int
. [uwagi poniżej (1,2)]
Stąd wynik jest taki sam jak wyrażenie sizeof(int)
, na twojej platformie.
Uwaga 1: cytowanie C11
, Rozdział §7.18, Boolean type and values <stdbool.h>
[....] Pozostałe trzy makra są odpowiednie do użycia w
#if
przetwarzaniu wstępnym dyrektywy. Oni are
true
Który rozszerza się do stałej całkowitej 1,
false
Który rozszerza się do stałej całkowitej 0, [....]
Uwaga 2: dla operatora warunkowego, rozdział §6.5.15, ( podkreślenie mine )
Pierwszy operand jest oceniany; pomiędzy jego oceną a ocena drugiego lub trzeciego operanda (w zależności od tego, która z tych wartości jest oceniana). Drugi operand na oceniany tylko wtedy, gdy pierwszy porównuje nierówność do 0; trzeci operand jest oceniany tylko wtedy, gdy pierwsze porównanie jest równe 0; wynikiem jest wartość drugiego lub trzeciego operandu (w zależności od tego, która z tych wartości jest oceniana), [...]
I
Jeśli zarówno drugi, jak i trzeci operand mają typ arytmetyczny, Typ wyniku, który byłby określone zwykłymi konwersjami arytmetycznymi, czy zostały one zastosowane do tych dwóch operandów, jest typem wyniku. [....]
Stąd wynik będzie typu integer, a ze względu na zakres wartości, stałe są dokładnie typu int
.
To powiedziawszy, ogólna rada, int main()
powinna być lepiej int main (void)
, aby być naprawdę zgodnym z normami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-30 10:33:29
Operatorem trójdzielnym jest czerwony śledź.
printf("%zu\n", sizeof(true));
Prints 4 (lub cokolwiek sizeof(int)
jest na twojej platformie).
Poniższe założenie zakłada, że bool
jest synonimem char
lub podobnego typu O rozmiarze 1, A {[4] } jest większy od char
.
Powodem, dla którego sizeof(true) != sizeof(bool)
i sizeof(true) == sizeof(int)
jest po prostu to, że true
jest , a nie wyrażeniem typu bool
. Jest to wyrażenie typu int
. Jest #define
d jak 1
w stdbool.h
.
nie ma wartości R typu Edit: ten akapit nie jest prawdziwy, argumenty do bool
W C przy wszystkie. Każda taka wartość R jest natychmiast promowana do int
, nawet jeśli jest używana jako argument do sizeof
.sizeof
nie awansują do int
. Nie wpływa to jednak na żadne z wniosków.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 08:08:00
Jeśli chodzi o typ logiczny w C
Typ boolean został wprowadzony dość późno w języku C, W roku 1999. Wcześniej C nie miało typu boolean, ale zamiast tego używało int
dla wszystkich wyrażeń boolean. Dlatego wszystkie operatory logiczne, takie jak > == !
etc zwracają int
o wartości 1
lub 0
.
Było zwyczajem, aby aplikacje używały domowych typów, takich jak typedef enum { FALSE, TRUE } BOOL;
, co również sprowadza się do typów o rozmiarze int
.
C++ miał dużo lepszy i jawny Typ boolean, bool
, który nie był większy niż 1 bajt. Podczas gdy typy boolean lub wyrażenia w C skończyłyby się jako 4 bajty w najgorszym przypadku. W C++ wprowadzono pewną zgodność ze standardem C99. C otrzymuje Typ boolean _Bool
oraz nagłówek stdbool.h
.
stdbool.h
zapewnia pewną kompatybilność z C++. Ten nagłówek definiuje makro bool
(ta sama pisownia co słowo kluczowe C++), które rozszerza się do _Bool
, typu, który jest małą liczbą całkowitą, prawdopodobnie o 1 bajt. Podobnie nagłówek zawiera dwa makra true
i false
, pisownia taka sama jak słowa kluczowe C++, , ale z kompatybilnością wsteczną do starszych programów C . Dlatego true
i false
rozszerzają się do 1
i 0
W C, a ich typem jest int
. Te makra nie są w rzeczywistości typu boolean, jak odpowiednie słowa kluczowe C++.
Podobnie, dla celów zgodności wstecznej operatory logiczne w C nadal zwracają int
do dnia dzisiejszego, nawet jeśli C obecnie ma Typ boolean. W C++ operatory logiczne zwracają bool
. Tak więc wyrażenie takie jak sizeof(a == b)
da rozmiar int
W C, ale rozmiar bool
W C++.
Odnośnie operatora warunkowego?:
Operator warunkowy ?:
jest dziwnym operatorem z kilkoma dziwactwami. Powszechnym błędem jest przekonanie, że jest ona w 100% równoważna if() { } else {}
. Niezupełnie.
Istnieje punkt sekwencji między oceną 1. A 2. lub 3. operand. Operator ?:
ma gwarancję, że będzie oceniał tylko 2. lub 3. operand, więc nie będzie mógł wykonać żadnych efektów ubocznych tego operandu, który nie jest oceniany. Kod podobny do true? func1() : func2()
nie wykona func2()
. Jak na razie dobrze.
jednak, istnieje specjalna zasada mówiąca, że 2.i 3. operand muszą być domyślnie promowane i zrównoważone względem siebie za pomocą zwykłych konwersji arytmetycznych. (zasady promocji typu Implicit w C wyjaśnione tutaj ). Oznacza to, że 2. lub 3. operand będzie zawsze był co najmniej tak duży jak int
.
Więc nie ma znaczenia, że true
i false
przypadkiem są typu int
W C, ponieważ wyrażenie zawsze dawałoby co najmniej rozmiar int
bez względu na to.
nawet jeśli przepisz wyrażenie do sizeof(a ? (bool)true : (bool)false)
i tak zwróci rozmiar int
!
Wynika to z niejawnej promocji typu poprzez zwykłe konwersje arytmetyczne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-01 06:29:38
Szybka odpowiedź:
-
sizeof(a ? true : false)
oblicza się na4
Ponieważtrue
ifalse
są zdefiniowane w<stdbool.h>
jako1
i0
, więc wyrażenie rozszerza się dosizeof(a ? 1 : 0)
, które jest wyrażeniem całkowitym o typieint
, które zajmuje 4 bajty na twojej platformie. Z tego samego powodu,sizeof(true)
również oceniłby4
w Twoim systemie.
Zauważ jednak, że:
sizeof(a ? a : a)
również ewaluuje do4
, ponieważ operator trójdzielny wykonuje liczbę całkowitą na drugim i trzecim operandach, jeśli są to wyrażenia całkowite. To samo oczywiście dzieje się dlasizeof(a ? true : false)
isizeof(a ? (bool)true : (bool)false)
, ale odlewanie całego wyrażenia jakobool
zachowuje się zgodnie z oczekiwaniami:sizeof((bool)(a ? true : false)) -> 1
.Należy również zauważyć, że operatory porównania oceniają wartości logiczne
1
lub0
, ale mają typint
:sizeof(a == a) -> 4
.
Jedynymi operatorami, które zachowują boolowską naturę a
będą:
Operator przecinka: zarówno
sizeof(a, a)
, jak isizeof(true, a)
oceniają na1
w czasie kompilacji.Operatory przypisania: zarówno
sizeof(a = a)
, jak isizeof(a = true)
mają wartość1
.Operatory przyrostowe:
sizeof(a++) -> 1
Wreszcie, wszystkie powyższe odnosi się tylko do C: C++ ma różne semantyki dotyczące typu bool
, wartości logicznych true
i false
, operatorów porównawczych i operatora trójdzielnego: wszystkie te wyrażenia sizeof()
oceniają się na 1
W C++.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-13 14:37:16
Oto fragment, z którego pochodzi to, co zawiera źródło
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#else /* __cplusplus */
Tam makra true
i false
są zadeklarowane odpowiednio jako 1 i 0.
Jednak w tym przypadku typ jest typem stałych literalnych. Zarówno 0, jak i 1 są stałymi całkowitymi, które mieszczą się w int, więc ich typem jest int.
I sizeof(int)
w Twoim przypadku jest 4.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-05 11:42:34
Nie ma boolean datatype w C, zamiast tego wyrażenia logiczne oceniają do wartości całkowitych 1
gdy true, w przeciwnym razie 0
.
Wyrażenia warunkowe jak if
, for
, while
, lub c ? a : b
oczekuj liczby całkowitej, jeśli liczba jest niezerowa, jest ona rozważana true
z wyjątkiem niektórych szczególnych przypadków, oto funkcja sumy rekurencyjnej, w której operator trójkowy będzie oceniał true
aż n
osiągnie 0
.
int sum (int n) { return n ? n+sum(n-1) : n ;
Może być również używany do NULL
sprawdzania wskaźnika, oto rekurencyjny funkcja, która wyświetla zawartość listy pojedynczo połączonej.
void print(sll * n){ printf("%d -> ",n->val); if(n->next)print(n->next); }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-03 12:31:01