“Sizeof (a? True: false)” neden dört baytlık çıktı veriyor?


133

sizeofÜçlü operatör ile operatör hakkında küçük bir kod parçası var :

#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;
}

Çıktı ( GCC ):

1
1
4 // Why 4?

Ama burada,

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

üçlü operatör C türünü döndürür booleanve C boolcinsinden sizeof türünü 1bayt eder.

Öyleyse neden sizeof(a ? true : false)dört baytlık bir çıktı veriyor?


39
sizeof(true)ve sizeof(false)ayrıca 4: ide.geeksforgeeks.org/O5jvuN
tkausl

7
Bu uygulama "tutarsız" açıkça tanımlayan ki neden burada daha ilginç bir soru olurdu _Boolboyutu 1 değil, sahip olmak trueve false. Ancak standardın söyleyebildiğim kadarıyla bunun hakkında söyleyecek bir şeyi yok.

12
@FelixPalmen aynı nedenle verilen char a; sizeof(a) == 1ve sizeof('a') == sizeof(int)(C). Uygulama ile ilgili değil, dil ile ilgili.
n. 'zamirler' m.

10
Yazdırmaya çalıştınız mı sizeof(true)? belki incileri biraz daha açık hale getirecektir (özellikle üçlü operatörün kırmızı bir ringa balığı olduğu aşikar hale gelecektir).
n. 'zamirler' m.

4
@FelixPalmen trueisimli #defined 1 olduğu stdbool.hyani Evet, bu gerçek bir tanımıdır.
n. 'zamirler' m.

Yanıtlar:


223

Çünkü sahipsin #include <stdbool.h>. Bu başlık tanımlar makro true ve falseolmaya 1ve 0bu gibi deyimi görünüyor böylece:

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

sizeof(int) platformunuzda 4.


21
"Çünkü #include <stdbool.h>" Hayır, öyle değil. sizeof(a ? (uint8_t)1 : (uint8_t)0);Ayrıca 4 bir bir sonuç tamsayı promosyon verecek ?:işlenen önemli burada parçası değil boyutudur trueve false.
Lundin

9
@Lundin: Her ikisi de önemlidir. Yazıldığı gibi, tür zaten inttanıtımsızdır. Bunu "düzeltememenizin" nedeni varsayılan promosyonlardır.
R .. GitHub BUZA YARDIMCI DURDUR

5
@PeterSchneider Bu C ++ değil. Bu ++ C de C, trueve falsevardır olmayan makro; anahtar kelimelerdir. Onlar olmak tanımlanmamış 1ve 0ancak doğru ve yanlış değerlerini gösterdiği booltip.
Justin

5
@PeterSchneider Hayır, bugün C hakkında bir şeyler öğrendiniz. İki dili karıştırmayın. C ++ 'da sizeof(true), 1. demo .
Rakete1111

1
Doğru, karıştırdım. Dikkatle okumuştu ve cppreference-link tarafından kaçırıldı. Benim hatam, teşekkürler. Ama yine de c ++ hakkında bu his var.
Peter Schneider

66

Burada üçlü operatör dönüş booleantürü,

Tamam, bundan daha fazlası var!

C'de, bu üçlü işlemin sonucu türdür int. [aşağıdaki notlar (1,2)]

Dolayısıyla sonuç, sizeof(int)platformunuzdaki ifadeyle aynıdır .


Not 1: Alıntı C11, bölüm §7.18,Boolean type and values <stdbool.h>

[....] Kalan üç makro #ifönişleme direktiflerinde kullanım için uygundur . Onlar

true

1 tamsayı sabitine genişleyen,

false

0, [....] tamsayı sabitine genişler

Not 2: Koşullu operatör için, bölüm §6.5.15, ( vurgu mayını )

İlk işlenen değerlendirilir; değerlendirmesi ile ikinci veya üçüncü işlenenin değerlendirilmesi arasında (hangisi değerlendirilirse) bir sıralama noktası vardır. İkinci işlenen, yalnızca ilki 0 ile eşit değilse karşılaştırılır; üçüncü işlenen, yalnızca birinci işlenen 0'a eşitse değerlendirilir; sonuç (hangisi değerlendirilirse) ikinci veya üçüncü işlenenin değeridir, [...]

ve

Hem ikinci hem de üçüncü işlenenler aritmetik tipe sahipse, bu iki işlenene uygulandıklarında olağan aritmetik dönüşümlerle belirlenecek sonuç türü, sonucun türüdür. [....]

dolayısıyla, sonuç tamsayı türünde olur ve değer aralığı nedeniyle sabitler tam olarak türdendir int.

Bununla birlikte, genel bir tavsiye, gerçekten standartlara uygun olmak int main()daha iyi olmalıdır int main (void).


@ user694733 umm .. neden olmasın? <stdbool.h>MACROS türünü tanımlar .. intbu yanlış mı?
Sourav Ghosh

@BasileStarynkevitch Tamam, şimdi görüyorum, bu gerçekten yanlış görünüyor, şimdi güncellendi.
Sourav Ghosh

58

Üçlü operatör kırmızı bir ringa balığıdır.

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

4 (veya sizeof(int)platformunuzda ne varsa) yazdırır .

Aşağıda bool, char1 boyutuyla eşanlamlı veya benzer bir tür olduğu ve intdaha büyük olduğu varsayılmaktadır char.

Nedeni sizeof(true) != sizeof(bool)ve sizeof(true) == sizeof(int)çünkü basitçe trueolduğu değil tip bir ifadesidir bool. Bu bir tür ifadesidir int. Bu olduğu #defineşekilde gün 1içinde stdbool.h.

boolC'de hiçbir tür rvalü yoktur . Bu tür her bir değer int, bir argüman olarak kullanıldığında bile derhal yükseltilir sizeof. Düzenleme: bu paragraf doğru değil, sizeofterfi terfi almak için int. Bu sonuçların hiçbirini etkilemez.


Güzel cevap. Şu anda en çok oylanan cevabı okuduktan sonra, tüm ifadelerin 4'e değer vermesi gerektiğini düşünüyordum. +1
Pedro A

5
Is not (bool)1türünde bir rvalue bool?
Ben Voigt

printf("%u\n", sizeof((char) 1));baskılar 1oysa benim platformda printf("%u\n", sizeof(1));baskılar 4. Bu, sizeof'e argüman olarak kullanıldığında bile, "Bu tür her bir değer hemen int'e yükseltilir" ifadenizin yanlış olduğu anlamına gelmez mi?
JonatanE

Bu soruya gerçekten cevap vermiyor. Herhangi bir şekilde tamsayı terfi ettiği için truevb . Boyut ve türü gerçekten önemli değildir . Yani, cevap neden kırmızı bir ringa balığı olduğunu ele almalıdır . ?:int ?:
Lundin

6
Cevabın konuyu en iyi şekilde ele aldığını düşünüyorum. Aşağı indirmek veya geliştirmek için bekliyoruz.
n. 'zamirler' m.

31

C'deki boole türü ile ilgili

1999 yılında C dilinde oldukça geç bir boole türü getirildi. O zamandan önce C'nin bir boole türü yoktu, bunun yerine inttüm boole ifadeleri için kullanılıyordu . Bu nedenle, > == !vb. Gibi tüm mantıksal işleçler bir intdeğer 1veya döndürür 0.

Uygulamaların typedef enum { FALSE, TRUE } BOOL;, aynı zamanda intboyutlandırılmış türlere de kaybolan gibi ev yapımı türleri kullanması özeldi.

C ++, bool1 bayttan daha büyük olmayan çok daha iyi ve açık bir boole tipine sahipti. C'deki boole türleri veya ifadeleri en kötü durumda 4 bayt olarak sonuçlanır. C ++ ile bir çeşit uyumluluk C'de C99 standardı ile getirilmiştir. C daha sonra bir boole türü _Boolve üstbilgi aldı stdbool.h.

stdbool.hC ++ ile bazı uyumluluk sağlar. Bu üstbilgi , büyük olasılıkla 1 bayt büyüklüğünde küçük bir tamsayı türü olan bir türe boolgenişleyen makroyu (C ++ anahtar sözcüğüyle aynı yazım) tanımlar _Bool. Benzer şekilde, başlık iki makro trueve falseC ++ anahtar sözcükleriyle aynı yazım denetimi sağlar, ancak eski C programlarıyla geriye dönük uyumluluk sağlar . Bu nedenle trueve falsegenişletmek 1ve 0C ve bunların türüdür int. Bu makrolar aslında karşılık gelen C ++ anahtar kelimeleri gibi boole türü değildir.

Benzer şekilde, geriye dönük uyumluluk amaçları için, C'nin mantıksal operatörleri, günümüzde C'nin bir boole türü olmasına rağmen, hala bir intgüne dönmektedir . C ++ ile çalışırken, mantıksal işleçler a döndürür bool. Bu durumda, bu tür bir ifade sizeof(a == b), bir boyutunu verecek intC, fakat boyutu boolC ++.

Koşullu operatör hakkında ?:

Koşullu operatör ?:, birkaç tuhaflığı olan garip bir operatördür. % 100'e eşdeğer olduğuna inanmak yaygın bir hatadır if() { } else {}. Pek değil.

1. ve 2. ya da 3. işlenenin değerlendirilmesi arasında bir sıralama noktası vardır. ?:Sadece 2 ya da 3 işlenen ya değerlendirmek o değerlendirilmez işlenen herhangi yan etkilerini yürütmek olamaz yani operatörü, garanti edilir. Like kodu true? func1() : func2()yürütülmez func2(). Çok uzak çok iyi.

Bununla birlikte , 2. ve 3. işlenenlerin, normal aritmetik dönüşümlerle birbirine karşı örtülü olarak tanıtılması ve dengelenmesi gerektiğini belirten özel bir kural vardır . ( Burada açıklanan C'deki örtük tür tanıtım kuralları ). Bu, 2. veya 3. işlenenin daima en az bir int.

Yani bunun bir önemi yok trueve C'de bir falsetür oluyor intçünkü ifade her zaman en azından bir maddenin büyüklüğünü verecekti int.

İfadeyi yeniden yazsanız bile yine de bir !sizeof(a ? (bool)true : (bool)false) int

Bunun nedeni, normal aritmetik dönüşümler aracılığıyla örtük tür tanıtımından kaynaklanmaktadır.


1
C ++ aslında garanti etmez sizeof(bool)==1.
aschepler

1
@aschepler Hayır ancak C ++ standardı dışındaki gerçek dünya bunu garanti eder. Derleyiciye
Lundin

Selam. Bu cevabın ilk kısmı olmasa daha iyi olacağını düşünüyorum . İkinci bölüm soruyu cevaplıyor. Gerisi ilginç olsa da sadece gürültü.
YSC

@YSC Bu aslında C ve C ++ olarak etiketlendi, bu nedenle farklı bool türleri ve arkalarındaki tarih arasında bir karşılaştırma gerekliydi. C ++ etiketi için değilse ilk bölümü yazmış olurdu şüpheliyim. Bununla birlikte, C'de sizeof (bool) 'un neden 1, fakat sizeof (false)' un 4 olduğunu anlamak gerekir
Lundin

21

Hızlı cevap:

  • sizeof(a ? true : false)için değerlendirir 4nedeniyle trueve falsede tanımlandığı <stdbool.h>şekilde 1ve 0sırasıyla sentezleme genişletir, böylece sizeof(a ? 1 : 0)tipi tam sayılı ifadesi olan intplatforma 4 byte kaplar. Aynı nedenden dolayı, sisteminizde sizeof(true)de değerlendirirsiniz 4.

Ancak şunu unutmayın:

  • sizeof(a ? a : a)Ayrıca 4, üçlü işleç, tamsayı ifadeleriyse ikinci ve üçüncü işlenenlerinde tamsayı yükseltmeleri gerçekleştirdiği için de değerlendirir . Elbette aynı yönelik olur sizeof(a ? true : false)ve sizeof(a ? (bool)true : (bool)false)ancak olarak tüm ifade döküm boolbeklendiği gibi davranır: sizeof((bool)(a ? true : false)) -> 1.

  • Ayrıca karşılaştırma işleçleri mantıksal değerlere değerlendirmek dikkat 1ya 0ama sahip inttürü: sizeof(a == a) -> 4.

Boole doğasını koruyan tek operatörler a:

  • virgül operatörü: her ikisi de sizeof(a, a)ve derleme zamanında sizeof(true, a)değerlendirmek 1.

  • atama operatörleri: Her iki sizeof(a = a)ve sizeof(a = true)bir değere sahiptir 1.

  • artış operatörleri: sizeof(a++) -> 1

Son olarak, yukarıdakilerin tümü yalnızca C için geçerlidir: C ++, booltür, boole değerleri trueve falsekarşılaştırma işleçleri ve üçlü operatör ile ilgili farklı anlambilime sahiptir : bu sizeof()ifadelerin tümü 1C ++ ile değerlendirilir .


2
Gerçekten ne tür trueve ne olduğu önemli olmadığını gösteren başarılı cevap false, çünkü ?:işlenenler bir şekilde tamsayı terfi ettireceklerdi int. Böylece sizeof(a ? (uint8_t)true : (uint8_t)false)sonuç olarak 4 elde edilir.
Lundin

Bu cevap ana önemli noktayı, değerin terfi edilmesini kapsarint
Chinni

1

İşte kaynağa dahil olan bir pasaj

#ifndef __cplusplus

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

#else /* __cplusplus */

Orada makrolar trueve falsesırasıyla 1 ve 0 olarak ilan edilir.

ancak bu durumda tür değişmez sabitlerin türüdür. Hem 0 hem de 1, bir int'e uyan tamsayı sabitleridir, bu nedenle türleri int'dir.

ve sizeof(int)sizin durumunuzda 4.


-3

C'de boole veri türü yoktur, bunun yerine mantıksal ifadeler 1aksi takdirde true olduğunda tamsayı değerlere göre değerlendirilir 0.

Koşullu ifadeler gibi if, for, while, veya c ? a : bsayı olarak kabul sıfırdan ise, bir tamsayı bekliyoruz truebazı özel durumlar dışında, burada üçlü-operatör değerlendirecek olan bir özyinelemeli toplamı fonksiyonu bulunuyor truekadar nulaşabileceği 0.

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

NULLBir işaretçiyi kontrol etmek için de kullanılabilir , burada Tekli Bağlantılı Listenin içeriğini yazdıran özyinelemeli bir işlev.

void print(sll * n){ printf("%d -> ",n->val); if(n->next)print(n->next); }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.