Deklarowanie zmiennej z dwoma typami: „int char”

81

Jestem początkującym C ++ i czytam Bjarne Stroustrup's Programming: Principles and Practice Using C ++ .

W sekcji 3.9.2 Niebezpieczne konwersje , wspomniał autor

Gdy inicjalizator jest literałem liczby całkowitej, kompilator może sprawdzić rzeczywistą wartość i zaakceptować wartości, które nie oznaczają zawężenia:

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

Zdziwi mnie ta deklaracja. Używa dwóch typów ( inti char). Nigdy wcześniej nie widziałem takiej deklaracji w Javie i Swifcie (dwóch językach, które stosunkowo dobrze znam). Czy to pomyłka czy prawidłowa składnia C ++?

Thor
źródło
2
Jakie masz wydanie i druk książki? Czy szukałeś erraty w książce?
Jakiś programista,
2
Więc jaką wersję czytasz? Jestem pewien, że Bjarne chciałby wiedzieć o tym błędzie.
StoryTeller - Unslander Monica
1
3.9.2 Niebezpieczne konwersje Przez niebezpieczną konwersję rozumiemy, że wartość może zostać niejawnie zamieniona na wartość innego typu, która nie jest równa wartości oryginalnej. np .: int i = 20000; char c = i; Takie konwersje nazywane są konwersjami „zawężającymi”. double to int, char lub bool int to char lub bool char to bool
Marichyasana
15
Jest float charto kolejny przydatny typ, szczególnie w basenach. Niektóre są wyposażone w uchwyt na piwo.
Yakk - Adam Nevraumont
1
Czy to pomyłka czy prawidłowa składnia C ++? Spróbuj (OK, OK, nie, to nieważne).
Paul Sanders,

Odpowiedzi:

95

To błąd w książce. To nie jest prawidłowa deklaracja C ++, nawet bez rzekomej konwersji zawężającej.

Nie ma o tym wzmianki w żadnej z errat na stronie Bjarne Stroustrupa (czwarty druk i wcześniejsze), co jest dziwne. To wystarczająco jasny błąd. Wyobrażam sobie, że skoro jest to skomentowane, //errorniewiele osób zauważy błąd w samej deklaracji.

StoryTeller - Unslander Monica
źródło
Jaki był prawdopodobnie zamierzony przykład kodu w książce?
Pedro A,
8
@Hamsterrific char b1 {1000};(ponieważ spowodowałoby to błąd wspomniany w komentarzu). Chyba palce Bjarne'a były zmęczone tego dnia.
Paul Sanders,
1
@PaulSanders Zmęczony? Wpisał inttam dodatkowy ! :-)
Leo
1
@ LeoHeinsaar Lol. OK, więc za dużo kawy :) A może się zacina :)
Paul Sanders.
Tak: zmęczone palce. Wygląda na błąd „wytnij i wklej” z przykładu, który go poprzedził. W poprzednim przykładzie podaje dwie linie: int a {1000}; // OK [\ n] char b {a} // błąd: int -> char może zawęzić [\ n] i wygląda na to, że wyciął i wkleił ten przykład do następnego i nie mógł usunąć części "int" : int char b1 {1000}; // błąd: zawężanie (zakładając 8-bitowe znaki) [\ n] char b2 {48}; // OK [\ n]
L. Scott Johnson
24

Książka jest zła.

Sekwencja tokenów int char b1{1000};nie jest poprawna semantycznie C ++.

Próbujesz zadeklarować b1więcej niż jeden typ, co nie ma sensu.

Batszeba
źródło
10

To jest złe. W C / C ++ deklaracje wielu typów można uzyskać za pomocą unii. Na przykład:

union {
    int i;
    char c;
} var;

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

Pamięć jest taka sama, więc .c i .i są po prostu uchwytami typu dla tej samej wartości.

Alex
źródło
6

To jest błąd w składni C / C ++. Oprócz unions (patrz odpowiedź @Alex), istnieje sposób w C ++ na przechowywanie tylko jednego z dostępnych typów o nazwie std::variant(type-safe union):

#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
}
Val mówi Przywróć Monikę
źródło