Verwirrendes Verhalten von sizeof mit chars [duplicate]

Lesezeit: 10 Minuten

Benutzeravatar von AmanSharma
AmanSharma

#include <stdio.h>
#include <string.h>

int main(void)
{
    char ch="a";

    printf("sizeof(ch)          = %d\n", sizeof(ch));
    printf("sizeof('a')         = %d\n", sizeof('a'));
    printf("sizeof('a'+'b'+'C') = %d\n", sizeof('a'+'b'+'C'));
    printf("sizeof(\"a\")       = %d\n", sizeof("a"));
}

Dieses Programm verwendet sizeof Größen zu berechnen. Warum ist die Größe von 'a' unterschiedlich von der Größe ch (wo ch="a")?

sizeof(ch)          = 1
sizeof('a')         = 4
sizeof('a'+'b'+'C') = 4
sizeof("a")         = 2

  • Sie sollten verwenden %zu wie sizeof kehrt zurück size_t nicht int

    – Spikatrix

    4. Juli 2018 um 12:43 Uhr

  • Sie müssen dies entweder mit C oder C++ kennzeichnen, da dieser Code je nach Sprache sehr unterschiedliche Antworten liefert. Grundsätzlich hat C++ erkannt, dass C dumm war, und verschiedene offensichtliche Sprachfehler behoben, während C sich weigert, zuzugeben, dass es dumm ist.

    – Ludin

    4. Juli 2018 um 12:45 Uhr


  • Seltsame Interpretation des Wortes “duplizieren” hier. Ich habe wieder geöffnet. Festplatte ist billig. Suchmaschinen sind mächtig. Lassen Sie uns nur als Duplikate schließen, wenn es sich um ein Duplikat handelt.

    – Bathseba

    4. Juli 2018 um 12:52 Uhr

  • @Bathsheba “Festplatte ist billig” ist kein Grund …

    – Benutzer202729

    4. Juli 2018 um 15:35 Uhr

  • @ user202729 Es ist nicht zu breit. Es stellt eine sehr spezifische, reale Frage zum Software-Engineering. Und es scheint kein exaktes Duplikat zu haben.

    – Davislor

    4. Juli 2018 um 23:10 Uhr

Benutzeravatar von Sourav Ghosh
Sourav Ghosh

TL;DRsizeof arbeitet an der Typ des Operanden.

  • sizeof(ch) == sizeof (char)——————-(1)
  • sizeof('a') == sizeof(int) ——————–(2)
  • sizeof ('a'+ 'b' + 'c') == sizeof(int) —(3)
  • sizeof ("a") == sizeof (char [2]) ———-(4)

Sehen wir uns jetzt jeden Fall an.

  1. ch ist definiert als von char Typ, also ziemlich einfach.

  2. In C, sizeof('a') ist das gleiche wie sizeof (int)da eine Zeichenkonstante vom Typ Integer ist.

    Zitieren C11,

    Eine ganzzahlige Zeichenkonstante hat einen Typ int. […]

    In C++ ein Zeichen wörtlich Typ hat char.

  3. sizeof ein Kompilierungsoperator ist (außer wenn der Operand ein VLA ist), also wird der Typ des Ausdrucks verwendet. Wie zuvor sind alle Integer-Zeichenkonstanten vom Typ intAlso int + int + int produziert int. Der Typ des Operanden wird also angenommen als int.

  4. "a" ist ein Array von zwei chars, 'a' und 0 (Null-Terminator) (Nein, es zerfällt nicht, um auf das erste Element des Array-Typs zu verweisen), daher ist die Größe die gleiche wie bei einem Array mit zwei char Elemente.


Das sagte schließlich, sizeof erzeugt ein Ergebnis vom Typ size_talso müssen Sie verwenden %zu Formatbezeichner, um das Ergebnis zu drucken.

  • Ich frage mich, welche Probleme, wenn überhaupt, sich aus der Herstellung ergeben hätten sizeof nur auf lvalues ​​operieren? Besonders auf Systemen, die FLT_EVAL_METHOD==2 verwenden und eine haben long double Typ, der größer ist als doublees wäre ein bisschen seltsam, das vorzuschlagen sizeof (1.0/10.0) sollte 8 melden, auch wenn long double d = (1.0/10.0); würde einen Wert speichern, der nicht in einem 8-Byte-Double dargestellt werden kann.

    – Superkatze

    4. Juli 2018 um 18:04 Uhr

  • Schlagen Sie vor “Zeichenkonstante hat Typ Integer” –> “Zeichenkonstante hat Typ int“.

    – chux – Wiedereinsetzung von Monica

    4. Juli 2018 um 20:03 Uhr

  • @supercat Unter anderem hätte es wahrscheinlich das folgende Konstrukt illegal gemacht: sizeof(type).

    – dgnuff

    5. Juli 2018 um 4:01 Uhr

  • @dgnuff: Mea culpa. Was ich meinte, war das Ausschließen des Operators für Werte, die keine lvalues ​​sind.

    – Superkatze

    5. Juli 2018 um 6:59 Uhr

  • @supercat, relativ wenige Probleme, vermute ich. Zum einen ein bisschen kognitive Dissonanz: Das ist schön konsistent sizeof arbeitet an alle Ausdrücke. Bei praktischen Programmierproblemen sehe ich den Fall, in dem Sie die Größe eines Zeichenfolgenliterals wünschen, und insbesondere dort, wo dieses Literal über ein Makro übermittelt wird, sodass seine Größe an einer Stelle geändert werden kann, die von seiner Verwendung entfernt ist — vielleicht sogar auf der Compiler-Kommandozeile.

    – Johannes Bollinger

    5. Juli 2018 um 13:53 Uhr


Benutzeravatar von Bathsheba
Bathseba

In C, 'a' ist Konstante des Typs int. es ist nicht a char. So sizeof('a') wird dasselbe sein wie sizeof(int).

sizeof(ch) ist das gleiche wie sizeof(char). (Der C-Standard garantiert, dass alle alphanumerischen Konstanten – und einige andere – der Form 'a' kann in ein passen charAlso char ch="a"; ist immer wohldefiniert.)

Beachten Sie, dass in C++ 'a' ist ein wörtlich des Typs char; noch ein weiterer Unterschied zwischen C und C++.

In C, sizeof("a") ist sizeof(char[2]) das ist 2. sizeof stiftet das nicht an Verfall eines Array-Typs auf einen Zeiger.

In C++, sizeof("a") ist sizeof(const char[2]) das ist 2. sizeof stiftet das nicht an Verfall eines Array-Typs auf einen Zeiger.

In beiden Sprachen, 'a'+'b'+'C' ist ein int Typ aufgrund der impliziten Heraufstufung ganzzahliger Typen in C++.

  • Tolle Antwort, aber für das sehr kleine Problem, nicht explizit darüber zu sein 'a'+'b'+'C' ein Beispiel dafür sein ganzheitliche Förderungnicht integrale Umwandlung, in Standardbegriffen. (Beide sind Konvertierungen weil dieser auch als Überbegriff verwendet wird. Die Namensgebung ist … interessant.)

    – Arne Vogel

    4. Juli 2018 um 14:06 Uhr

  • @ArneVogel: Danke, wenn ich jedes Mal einen Dollar hätte, wenn ich das falsch sage oder schreibe…

    – Bathseba

    4. Juli 2018 um 14:07 Uhr

  • @chux Danke, ich habe es behoben, aber ich denke, ich lasse das ganze C++-Zeug oben – die Freuden einer bewegenden Frage!

    – Bathseba

    4. Juli 2018 um 20:10 Uhr

Zunächst einmal das Ergebnis sizeof Typ ist size_tdie mit gedruckt werden sollte %zu Formatbezeichner. Ignorieren Sie diesen Teil und nehmen Sie an int ist dann 4 Bytes

  • printf("sizeof(ch) %d\n",sizeof(ch)); gibt 1 in C und 1 in C++ aus.

    Dies liegt daran, dass a char ist per Definition garantiert 1 Byte in beiden Sprachen.

  • printf("sizeof('a') %d\n",sizeof('a')); gibt 4 in C und 1 in C++ aus.

    Dies liegt daran, dass Zeichenliterale vom Typ sind int in C, aus historischen Gründen1)aber sie sind vom Typ char in C++, weil es der gesunde Menschenverstand (und ISO 14882) vorschreibt.

  • printf("sizeof('a'+'b'+'C) %d\n",sizeof('a'+'b'+'C')); wird 4 in beiden Sprachen drucken.

    In C ist der resultierende Typ von int + int + int ist selbstverständlich int. In C++ haben wir char + char + char. Aber das + ruft implizite Type-Promotion-Regeln auf, also landen wir bei int am Ende egal.

  • printf("sizeof(\"a\") %d\n",sizeof("a")); wird 2 in beiden Sprachen drucken.

    Das Zeichenfolgenliteral "a" ist vom Typ char[] in C und const char[] in C++. In beiden Fällen haben wir ein Array bestehend aus an a und ein Null-Terminator: zwei Zeichen.

    Als Randnotiz geschieht dies, weil das Array "a" zerfällt beim Operanden to nicht in einen Zeiger auf das erste Element sizeof. Sollen wir zum Beispiel durch Schreiben einen Array-Zerfall provozieren sizeof("a"+0)dann würden wir stattdessen die Größe eines Zeigers erhalten (wahrscheinlich 4 oder 8).


1) Irgendwo im Mittelalter gab es keine Typen und alles, was Sie schrieben, würde darauf hinauslaufen int egal. Als Dennis Ritchie dann anfing, eine Art De-facto-Standard für C zusammenzukochen, entschied er anscheinend, dass Zeichenliterale immer so sein sollten gefördert zu int. Und später, als C standardisiert wurde, sagten sie, dass Zeichenliterale einfach sind int.

Bei der Erstellung von C++ erkannte Bjarne Stroustrup, dass all dies nicht viel Sinn machte und Zeichenliterale zum Typ machte char wie sie sein sollten. Aber das C-Komitee weigert sich hartnäckig, diesen Sprachfehler zu beheben.

  • Meine Exemplare definieren den C89 und C99 Standard sizeof um Zählungen von “Speichereinheiten” zurückzugeben, nicht von “Bytes”, was auch immer diese sind.

    – Eric Türme

    4. Juli 2018 um 19:08 Uhr

  • @EricTowers “Byte” wird heute normalerweise nur für 8 Bit verwendet, aber sizeof gibt die Anzahl von zurück chars – und ein C char kann größer als 8 Bit sein (es sind zum Beispiel 16 Bit auf einer CPU, mit der ich arbeite).

    – Rohr

    4. Juli 2018 um 19:54 Uhr

  • @pipe: Und ein Byte war 9 Bit auf Architekturen, an denen ich gearbeitet habe. Mein Punkt ist, dass, da der Standard “Byte” nicht definiert oder verwendet, es falsch ist, “ist per Definition garantiert 1 Byte”.

    – Eric Türme

    4. Juli 2018 um 19:56 Uhr

  • Detail: C-Standard hat nicht Zeichenliterale. Es hat Zeichenkonstanten welche Typ sind int. Die 2 Literale von C: Schnur und Verbindung können im Gegensatz zu Konstanten ihre Adresse übernehmen.

    – chux – Wiedereinsetzung von Monica

    4. Juli 2018 um 20:12 Uhr

  • @EricTowers C11/C99 ​​6.5.3.4/2 oder C90 6.3.3.4 “Der sizeof-Operator ergibt die Größe (in Bytes) seines Operanden”. Vielleicht das nächste Mal den Standard zitieren, bevor Sie solche Aussagen machen.

    – Ludin

    5. Juli 2018 um 6:15 Uhr


Wie andere bereits erwähnt haben, definiert der C-Sprachstandard den Typ einer Zeichenkonstante int. Der historische Grund dafür ist, dass C und sein Vorgänger B ursprünglich auf DEC PDP-Minicomputern mit verschiedenen Wortgrößen entwickelt wurden, die 8-Bit-ASCII unterstützten, aber nur mit Registern arithmetisch arbeiten konnten. Frühe Versionen von C definiert int die native Wortgröße der Maschine und jeder Wert kleiner als an sein int erweitert werden musste int um an oder von einer Funktion übergeben oder in einem bitweisen, logischen oder arithmetischen Ausdruck verwendet zu werden, denn so funktionierte die zugrunde liegende Hardware.

Das ist auch der Grund, warum die Integer-Promotion-Regeln immer noch besagen, dass jeder Datentyp kleiner als ein int befördert wird int. C-Implementierungen dürfen aus ähnlichen historischen Gründen auch Einser-Komplement-Mathematik anstelle von Zweier-Komplement verwenden, und die Tatsache, dass Zeichen-Escapes standardmäßig auf Oktal und Oktal-Konstanten beginnen, beginnt mit just 0 und Hex braucht \x oder 0x ist, dass diese frühen DEC-Minicomputer Wortgrößen hatten, die in Drei-Byte-Blöcke teilbar waren, aber keine Vier-Byte-Nibbles.

Automatische Beförderung zu int macht heute nichts als Ärger. (Wie viele Programmierer wissen, dass das Multiplizieren von zwei uint32_t Ausdrücke zusammen ist undefiniertes Verhalten, da einige Implementierungen definieren int B. 64 Bit breit, erfordert die Sprache, dass jede Art von niedrigerem Rang als int muss befördert werden zu a unterzeichnet intdas Ergebnis der Multiplikation von zwei int Multiplikanden hat einen Typ intdie Multiplikation kann ein signiertes 64-Bit-Produkt überlaufen lassen, und das ist ein undefiniertes Verhalten?) Aber das ist der Grund, warum C und C++ daran hängen bleiben.

Benutzeravatar von Wolf
Wolf

Ich gehe davon aus, dass der Code in C kompiliert wurde.
In C, 'a' wird als behandelt int Typ und int hat eine Größe von 4. In C++ 'a' wird als behandelt char type, und wenn Sie versuchen, Ihren Code in cpp.sh zu kompilieren, sollte es 1 zurückgeben.

  • int hat eine Größe von 4„Normalerweise ja. Aber nicht immer.

    – Spikatrix

    4. Juli 2018 um 12:56 Uhr

  • Ich habe eine Plattform, wo sizeof(int)==1.

    – Rohr

    4. Juli 2018 um 19:55 Uhr

  • @pipe Mit welcher Plattform/Compiler ist das sizeof(int)==1?

    – chux – Wiedereinsetzung von Monica

    4. Juli 2018 um 20:14 Uhr

  • @chux: Ich glaube, Cray XMP wird verwendet CHAR_BIT == 32 Also sizeof(int) == 1. Die meisten Menschen haben so etwas nicht mehr herumlaufen – oder die Strom- oder Wasserversorgung, die notwendig ist, um es glücklich zu machen.

    – Jonathan Leffler

    4. Juli 2018 um 22:39 Uhr


  • @chux Ein benutzerdefinierter Kern in einem kleinen eingebetteten Chip, wo CHAR_BIT==16 und ein int ist 16 Bit.

    – Rohr

    5. Juli 2018 um 6:47 Uhr

  • int hat eine Größe von 4„Normalerweise ja. Aber nicht immer.

    – Spikatrix

    4. Juli 2018 um 12:56 Uhr

  • Ich habe eine Plattform, wo sizeof(int)==1.

    – Rohr

    4. Juli 2018 um 19:55 Uhr

  • @pipe Mit welcher Plattform/Compiler ist das sizeof(int)==1?

    – chux – Wiedereinsetzung von Monica

    4. Juli 2018 um 20:14 Uhr

  • @chux: Ich glaube, Cray XMP wird verwendet CHAR_BIT == 32 Also sizeof(int) == 1. Die meisten Menschen haben so etwas nicht mehr herumlaufen – oder die Strom- oder Wasserversorgung, die notwendig ist, um es glücklich zu machen.

    – Jonathan Leffler

    4. Juli 2018 um 22:39 Uhr


  • @chux Ein benutzerdefinierter Kern in einem kleinen eingebetteten Chip, wo CHAR_BIT==16 und ein int ist 16 Bit.

    – Rohr

    5. Juli 2018 um 6:47 Uhr

1403420cookie-checkVerwirrendes Verhalten von sizeof mit chars [duplicate]

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

Privacy policy