Deklarieren einer Variablen mit zwei Typen: "int char"


81

Ich bin ein C ++ - Anfänger und lese Bjarne Stroustrups Programmierung: Prinzipien und Praxis mit C ++ .

Im Abschnitt 3.9.2 Unsichere Konvertierungen erwähnte der Autor

Wenn der Initialisierer ein ganzzahliges Literal ist, kann der Compiler den tatsächlichen Wert überprüfen und Werte akzeptieren, die keine Verengung implizieren:

int char b1 {1000};     // error: narrowing (assuming 8-bit chars)

Diese Erklärung verwirrt mich. Es werden zwei Typen ( intund char) verwendet. Ich habe noch nie eine solche Erklärung in Java und Swift gesehen (die beiden Sprachen, mit denen ich relativ vertraut bin). Ist das ein Tippfehler oder eine gültige C ++ - Syntax?


2
Welche Ausgabe und Drucke des Buches haben Sie? Haben Sie nach einer Errata des Buches gesucht?
Einige Programmierer Typ

2
Also, welche Version liest du? Ich bin sicher, Bjarne würde gerne etwas über diesen Fehler erfahren.
StoryTeller - Unslander Monica

1
3.9.2 Unsichere Konvertierungen Mit unsicherer Konvertierung ist gemeint, dass ein Wert implizit in einen Wert eines anderen Typs umgewandelt werden kann, der nicht dem ursprünglichen Wert entspricht. zB: int i = 20000; char c = i; Solche Konvertierungen werden als "Verengungskonvertierungen" bezeichnet. double to int, char oder bool int to char oder bool char to bool
Marichyasana

15
Dies float charist ein weiterer nützlicher Typ, insbesondere in Schwimmbädern. Einige kommen mit einem Halter für ein Bier.
Yakk - Adam Nevraumont

1
Ist das ein Tippfehler oder eine gültige C ++ - Syntax? Probieren Sie es aus (OK, OK, nein, es ist nicht gültig).
Paul Sanders

Antworten:


95

Es ist ein Fehler im Buch. Dies ist keine gültige C ++ - Deklaration, auch ohne die vermeintlich einschränkende Konvertierung.

Es wird jedoch in keiner der Erratas auf der Seite von Bjarne Stroustrup (4. Druck und früher) erwähnt, was seltsam ist. Es ist ein klarer Fehler. Ich stelle mir vor, da es mit //errorwenigen Leuten kommentiert wird , die den Fehler in der Erklärung selbst bemerken.


Was war wahrscheinlich das beabsichtigte Codebeispiel in dem Buch?
Pedro A

8
@ Hamsterrific char b1 {1000};(weil dies den im Kommentar erwähnten Fehler provozieren würde). Ich denke, Bjarnes Tippfinger waren an diesem Tag müde.
Paul Sanders

1
@ PaulSanders Müde? Er hat dort ein Extra getippt int! :-)
Leo Heinsaar

1
@ LeoHeinsaar Lol. OK, dann zu viel Kaffee :) Oder vielleicht hat er ein Stottern :)
Paul Sanders

Ja: Finger müde. Es sieht aus wie ein Fehler beim Ausschneiden und Einfügen aus dem vorhergehenden Beispiel. In diesem vorherigen Beispiel gibt er zwei Zeilen an: int a {1000}; // OK [\ n] char b {a} // Fehler: int -> char könnte sich einschränken [\ n] und er scheint dieses Beispiel für das nächste ausgeschnitten und eingefügt zu haben und das Löschen des "int" -Teils verpasst zu haben : int char b1 {1000}; // Fehler: Verengung (unter der Annahme von 8-Bit-Zeichen) [\ n] char b2 {48}; // OK [\ n]
L. Scott Johnson

24

Das Buch ist falsch.

Die Token-Sequenz int char b1{1000};ist in C ++ nicht semantisch gültig.

Sie versuchen, b1mit mehr als einem Typ zu deklarieren , was keinen Sinn ergibt.


10

Es ist falsch. In C / C ++ können die Deklarationen mit mehreren Typen über die Verwendung von Gewerkschaften erreicht werden. Z.B:

union {
    int i;
    char c;
} var;

var.i = 42;
/* OR */
var.c = ‘c’;

Der Speicher ist derselbe, daher sind .c und .i nur Typ-Handles mit demselben Wert.


6

Dies ist in der C / C ++ - Syntax falsch. Zusätzlich zu unions (siehe @ Alex-Antwort) gibt es eine C ++ - Möglichkeit, nur einen der verfügbaren Typen mit dem Namen std::variant(type-safe union) zu speichern :

#include <variant>
#include <string>

int main()
{
    std::variant<int, float> v, w;
    v = 12; // v contains int
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line
    w = v; // same effect as the previous line

//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1

    try {
      std::get<float>(w); // w contains int, not float: will throw
    }
    catch (std::bad_variant_access&) {}

    std::variant<std::string> v("abc"); // converting constructors work when unambiguous
    v = "def"; // converting assignment also works when unambiguous
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.