Warum gibt “sizeof(a ? true : false)” eine Ausgabe von vier Bytes aus?

Lesezeit: 10 Minuten

Benutzeravatar von msc
msc

Ich habe ein kleines Stück Code über die sizeof Operator mit dem ternären Operator:

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

Ausgabe (GCC):

1
1
4 // Why 4?

Aber hier,

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

der ternäre Operator kehrt zurück boolean Art und Größe bool Typ ist 1 Bytes in C.

Dann warum tut sizeof(a ? true : false) eine Ausgabe von vier Bytes geben?

  • sizeof(true) und sizeof(false) ist auch 4: ide.geeksforgeeks.org/O5jvuN

    – tkausl

    30. Oktober 2017 um 8:40 Uhr


  • Die interessantere Frage hier wäre, warum diese Implementierung “inkonsistent” ist, da sie offensichtlich definiert _Bool Größe 1 zu haben, aber nicht true und false. Aber dazu sagt die Norm meines Wissens nichts.

    Benutzer2371524

    30. Oktober 2017 um 9:02 Uhr

  • @FelixPalmen derselbe Grund, warum angegeben char a; sizeof(a) == 1 und sizeof('a') == sizeof(int) (in C). Es geht nicht um die Umsetzung, sondern um die Sprache.

    – n. 1.8e9-wo-ist-meine-Aktie m.

    30. Oktober 2017 um 9:12 Uhr

  • Haben Sie versucht zu drucken sizeof(true)? vielleicht wird es etwas klarer (insbesondere wird deutlich, dass der ternäre Operator ein Ablenkungsmanöver ist).

    – n. 1.8e9-wo-ist-meine-Aktie m.

    30. Oktober 2017 um 9:17 Uhr

  • @FelixPalmen true ist #defined zu 1 durch sein stdbool.h Also ja, das ist die wörtliche Definition.

    – n. 1.8e9-wo-ist-meine-Aktie m.

    30. Oktober 2017 um 9:29 Uhr

Es ist, weil Sie haben #include <stdbool.h>. Diese Überschrift definiert Makros true und false sein 1 und 0also sieht deine Aussage so aus:

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

sizeof(int) ist 4 auf Ihrer Plattform.

  • „Das liegt daran, dass Sie #include haben.“ Nein, ist es nicht. sizeof(a ? (uint8_t)1 : (uint8_t)0); würde auch ein Ergebnis von 4 ergeben. Die Integer-Promotion des ?: Operanden ist hier der wichtige Teil, nicht die Größe true und false.

    – Ludin

    31. Oktober 2017 um 9:14 Uhr


  • @Lundin: Beides ist wichtig. Wie geschrieben steht der Typ schon int ohne Förderung. Der Grund, warum Sie es nicht “reparieren” können, sind die Standardaktionen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    31. Oktober 2017 um 16:28 Uhr

  • @PeterSchneider Das ist nicht C++. Das ist C. In C++ true und false sind nicht Makros; sie sind Schlüsselwörter. Sie sind nicht so definiert 1 und 0sondern die wahren und falschen Werte von sein bool Typ.

    – Justin

    31. Oktober 2017 um 18:49 Uhr

  • @PeterSchneider Nein, du hast heute etwas über C gelernt. Verwechseln Sie die beiden Sprachen nicht. In C++, sizeof(true) ist 1. Demo.

    – Rakete1111

    31. Oktober 2017 um 18:52 Uhr


  • Richtig, verwechselt. Hatte nicht sorgfältig gelesen und wurde von cppreference-link in die Irre geführt. Meine Schuld, danke. Aber dieses Gefühl habe ich bei c++ sowieso.

    – Peter Schneider

    31. Oktober 2017 um 18:56 Uhr

Benutzeravatar von Sourav Ghosh
Sourav Ghosh

Hier ternäre Operatorrückgabe boolean Typ,

Okay, da ist noch mehr!

In C das Ergebnis von Dies ternärer Betrieb ist vom Typ int. [notes below (1,2)]

Daher ist das Ergebnis dasselbe wie der Ausdruck sizeof(int)auf Ihrer Plattform.


Anmerkung 1: Zitieren C11Kapitel §7.18, Boolean type and values <stdbool.h>

[….] Die verbleibenden drei Makros eignen sich für die Verwendung in #if Vorverarbeitungsanweisungen. Sie sind

true

die zur ganzzahligen Konstante 1 erweitert wird,

false

die zur ganzzahligen Konstante 0 erweitert wird, [….]

Hinweis 2: Für Bedingungsoperator, Kapitel §6.5.15, (Betonung von mir)

Der erste Operand wird ausgewertet; Es gibt einen Sequenzpunkt zwischen seiner Auswertung und der Auswertung des zweiten oder dritten Operanden (je nachdem, welcher ausgewertet wird). Der zweite Operand wird nur ausgewertet, wenn der erste ungleich 0 ist; der dritte Operand wird nur ausgewertet, wenn der erste gleich 0 ist; das Ergebnis ist der Wert des zweiten oder dritten Operanden (je nachdem, was ausgewertet wird), […]

und

Wenn sowohl der zweite als auch der dritte Operand einen arithmetischen Typ haben, ist der Ergebnistyp, der durch die üblichen arithmetischen Konvertierungen bestimmt würde, wenn sie auf diese beiden Operanden angewendet würden, der Typ des Ergebnisses. [….]

daher ist das Ergebnis vom Typ Integer und aufgrund des Wertebereichs sind die Konstanten genau vom Typ int.

Das heißt, ein allgemeiner Rat, int main() sollte besser sein int main (void) wirklich standardkonform zu sein.

  • @user694733 ähm..warum nicht? <stdbool.h> definiert die MACROS als vom Typ int..ist das falsch?

    – Sourav Ghosh

    30. Oktober 2017 um 8:44 Uhr

  • @BasileStarynkevitch OK, ich sehe das jetzt, das scheint in der Tat falsch zu sein, jetzt aktualisiert.

    – Sourav Ghosh

    30. Oktober 2017 um 8:48 Uhr

n.  Benutzeravatar von 1.8e9-where's-my-share m
n. 1.8e9-wo-ist-meine-Aktie m.

Der ternäre Operator ist ein Ablenkungsmanöver.

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

druckt 4 (oder was auch immer sizeof(int) befindet sich auf Ihrer Plattform).

Das Folgende geht davon aus bool ist ein Synonym für char oder ein ähnlicher Typ der Größe 1 und int ist größer als char.

Der Grund warum sizeof(true) != sizeof(bool) und sizeof(true) == sizeof(int) liegt einfach daran true ist nicht ein Ausdruck des Typs bool. Es ist ein Ausdruck des Typs int. es ist #defined wie 1 in stdbool.h.

Es gibt keine rvalues ​​vom Typ bool überhaupt in C. Jeder solche rvalue wird sofort zu befördert intauch wenn es als Argument für verwendet wird sizeof. Bearbeiten: Dieser Absatz ist nicht wahr, Argumente dazu sizeof nicht befördert werden int. Dies hat jedoch keinen Einfluss auf die Schlussfolgerungen.

  • Gute Antwort. Nachdem ich die derzeit am meisten positiv bewertete Antwort gelesen hatte, dachte ich, dass alle Aussagen mit 4 bewertet werden sollten. Dies klärte die Dinge auf. +1

    – Pedro A

    30. Oktober 2017 um 11:58 Uhr

  • Ist nicht (bool)1 ein rvalue vom Typ bool?

    – Ben Voigt

    30. Oktober 2017 um 19:53 Uhr

  • printf("%u\n", sizeof((char) 1)); Drucke 1 auf meiner Plattform während printf("%u\n", sizeof(1)); Drucke 4. Bedeutet dies nicht, dass Ihre Aussage “Jeder solche rvalue wird sofort zu int hochgestuft, auch wenn er als Argument für sizeof verwendet wird” falsch ist?

    – JonatanE

    31. Oktober 2017 um 7:48 Uhr

  • Das beantwortet die Frage nicht wirklich. Größe und Art der true usw. ist im Fall von nicht wirklich wichtig ?: da es ganzzahlig befördert wird int jedenfalls. Das heißt, die Antwort sollte ansprechen warum ?: ist ein roter Hering.

    – Ludin

    31. Oktober 2017 um 9:12 Uhr

  • Ich denke, die Antwort spricht das Problem auf die bestmögliche Weise an. Sie können es gerne ablehnen oder verbessern.

    – n. 1.8e9-wo-ist-meine-Aktie m.

    31. Oktober 2017 um 9:46 Uhr

Benutzeravatar von Lundin
Lundin

Bezüglich des booleschen Typs in C

Ein boolescher Typ wurde ziemlich spät in der Sprache C eingeführt, im Jahr 1999. Davor hatte C keinen booleschen Typ, sondern verwendet int für alle booleschen Ausdrücke. Daher alle logischen Operatoren wie z > == ! etc zurück an int von Wert 1 oder 0.

Für Anwendungen war es üblich, hausgemachte Typen wie z typedef enum { FALSE, TRUE } BOOL;was auch darauf hinausläuft int-große Typen.

C++ hatte einen viel besseren und expliziteren booleschen Typ, bool, die nicht größer als 1 Byte war. Während die booleschen Typen oder Ausdrücke in C im schlimmsten Fall als 4 Bytes enden würden. Eine gewisse Kompatibilität mit C++ wurde in C mit dem C99-Standard eingeführt. C bekam dann einen booleschen Typ _Bool und auch die Überschrift stdbool.h.

stdbool.h bietet eine gewisse Kompatibilität mit C++. Dieser Header definiert das Makro bool (gleiche Schreibweise wie das C++-Schlüsselwort), das erweitert wird zu _Bool, ein Typ, der ein kleiner ganzzahliger Typ ist, wahrscheinlich 1 Byte groß. In ähnlicher Weise stellt der Header zwei Makros bereit true und falsegleiche Schreibweise wie C++-Schlüsselwörter, aber mit Abwärtskompatibilität zu älteren C-Programmen. Deswegen true und false erweitern zu 1 und 0 in C und ihr Typ ist int. Diese Makros sind eigentlich nicht vom booleschen Typ, wie es die entsprechenden C++-Schlüsselwörter wären.

In ähnlicher Weise werden aus Gründen der Abwärtskompatibilität logische Operatoren in C still Rückkehr ein int bis heute, obwohl C heutzutage einen booleschen Typ hat. In C++ geben logische Operatoren a zurück bool. Also ein Ausdruck wie sizeof(a == b) gibt die Größe von an int in C, aber die Größe von a bool in C++.

Apropos Bedingungsoperator ?:

Der Bedingungsoperator ?: ist ein seltsamer Operator mit ein paar Macken. Es ist ein häufiger Fehler zu glauben, dass es zu 100% gleichwertig ist if() { } else {}. Nicht ganz.

Zwischen der Auswertung des 1. und des 2. bzw. 3. Operanden liegt ein Sequenzpunkt. Das ?: -Operator wertet garantiert nur den 2. oder 3. Operanden aus, sodass er keine Seiteneffekte des nicht ausgewerteten Operanden ausführen kann. Code wie true? func1() : func2() wird nicht ausgeführt func2(). So weit, ist es gut.

Jedochgibt es eine Sonderregel, die besagt, dass der 2. und 3. Operand implizit typaufgestuft und mit dem gegeneinander abgeglichen werden müssen übliche arithmetische Umrechnungen. (Implizite Heraufstufungsregeln in C werden hier erklärt). Das heißt, der 2. oder 3. Operand wird stets mindestens so groß wie ein sein int.

Das ist also egal true und false zufällig vom Typ sein int in C, weil der Ausdruck immer mindestens die Größe von an geben würde int egal.

Auch wenn Sie den Ausdruck umschreiben würden sizeof(a ? (bool)true : (bool)false) es würde immer noch die Größe von an zurückgeben int !

Dies liegt an der impliziten Typumwandlung durch die üblichen arithmetischen Konvertierungen.

Benutzeravatar von chqrlie
chqrlie

Schnelle Antwort:

  • sizeof(a ? true : false) wertet zu 4 Weil true und false sind darin definiert <stdbool.h> wie 1 und 0 bzw. erweitert sich der Ausdruck zu sizeof(a ? 1 : 0) Dies ist ein ganzzahliger Ausdruck mit Typ int, das auf Ihrer Plattform 4 Bytes belegt. Aus dem gleichen Grunde, sizeof(true) würde auch zu bewerten 4 auf Ihrem System.

Beachten Sie jedoch Folgendes:

  • sizeof(a ? a : a) wertet auch aus 4 weil der ternäre Operator die ganzzahligen Heraufstufungen an seinem zweiten und dritten Operanden durchführt, wenn es sich um ganzzahlige Ausdrücke handelt. Dasselbe gilt natürlich auch für sizeof(a ? true : false) und sizeof(a ? (bool)true : (bool)false)aber Casting des gesamten Ausdrucks als bool verhält sich wie erwartet: sizeof((bool)(a ? true : false)) -> 1.

  • Beachten Sie auch, dass Vergleichsoperatoren zu booleschen Werten ausgewertet werden 1 oder 0aber haben int Typ: sizeof(a == a) -> 4.

Die einzigen Operatoren, die die boolesche Natur von beibehalten a wäre:

  • der Kommaoperator: beides sizeof(a, a) und sizeof(true, a) auswerten zu 1 zur Kompilierzeit.

  • die Zuweisungsoperatoren: beide sizeof(a = a) und sizeof(a = true) einen Wert von haben 1.

  • die Inkrementoperatoren: sizeof(a++) -> 1

Schließlich gilt alles Obige nur für C: C++ hat eine andere Semantik in Bezug auf die bool Typ, boolesche Werte true und falseVergleichsoperatoren und der ternäre Operator: all dies sizeof() Ausdrücke werden ausgewertet 1 in C++.

  • Gute Antwort, die tatsächlich darauf hinweist, dass es nicht wirklich darauf ankommt, welcher Typ true und false sind, weil die ?: Operanden würden zur Ganzzahl befördert werden int jedenfalls. Daher sizeof(a ? (uint8_t)true : (uint8_t)false) ergibt auch 4 als Ergebnis.

    – Ludin

    31. Oktober 2017 um 9:10 Uhr


  • Diese Antwort deckt den wichtigsten wichtigen Punkt ab, nämlich den Wert, zu dem man befördert wird int

    – Chinni

    31. Oktober 2017 um 19:52 Uhr

Benutzeravatar von asio_guy
asio_kerl

Hier ist ein Ausschnitt aus dem, was in der Quelle enthalten ist

#ifndef __cplusplus

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

#else /* __cplusplus */

Es Makros true und false werden als 1 bzw. 0 deklariert.

In diesem Fall ist der Typ jedoch der Typ der Literalkonstanten. Sowohl 0 als auch 1 sind ganzzahlige Konstanten, die in ein int passen, also ist ihr Typ int.

und die sizeof(int) in Ihrem Fall ist 4.

  • Gute Antwort, die tatsächlich darauf hinweist, dass es nicht wirklich darauf ankommt, welcher Typ true und false sind, weil die ?: Operanden würden zur Ganzzahl befördert werden int jedenfalls. Daher sizeof(a ? (uint8_t)true : (uint8_t)false) ergibt auch 4 als Ergebnis.

    – Ludin

    31. Oktober 2017 um 9:10 Uhr


  • Diese Antwort deckt den wichtigsten wichtigen Punkt ab, nämlich den Wert, zu dem man befördert wird int

    – Chinni

    31. Oktober 2017 um 19:52 Uhr

Benutzeravatar von Khaled.K
Khaled.K

Es gibt keinen booleschen Datentyp in C, stattdessen werden logische Ausdrücke zu ganzzahligen Werten ausgewertet 1 wenn es sonst wahr ist 0.

Bedingte Ausdrücke wie if, for, whileoder c ? a : b Erwarten Sie eine Ganzzahl, wenn die Zahl nicht Null ist, wird sie berücksichtigt true Abgesehen von einigen Sonderfällen ist hier eine rekursive Summenfunktion, in der der ternäre Operator ausgewertet wird true bis um n erreichen 0.

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

Es kann auch verwendet werden NULL check a pointer, hier ist eine rekursive Funktion, die den Inhalt einer Single-Linked-List ausgibt.

void print(sll * n){ printf("%d -> ",n->val); if(n->next)print(n->next); }

1423660cookie-checkWarum gibt “sizeof(a ? true : false)” eine Ausgabe von vier Bytes aus?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy