Объявление переменной двух типов: int char

Я новичок в C++ и читаю книгу Бьерна Страуструпа Programming: Principles and Practice Using C++.

В разделе 3.9.2 Небезопасные преобразования автор упомянул

Когда инициализатор представляет собой целочисленный литерал, компилятор может проверить фактическое значение и принять значения, не подразумевающие сужение:

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

Я озадачен этим заявлением. Он использует два типа (int и char). Я никогда раньше не видел такого объявления в Java и Swift (два языка, с которыми я относительно знаком). Это опечатка или допустимый синтаксис C++?


person Thor    schedule 09.07.2018    source источник
comment
Какое издание и печать книги у вас есть? Вы искали опечатки в книге?   -  person Some programmer dude    schedule 09.07.2018
comment
@Someprogrammerdude спасибо за напоминание. Я должен обязательно проверить опечатки в первую очередь.   -  person Thor    schedule 09.07.2018
comment
Так какую версию вы читаете? Я уверен, что Бьерн хотел бы знать об этой ошибке.   -  person StoryTeller - Unslander Monica    schedule 09.07.2018
comment
3.9.2 Небезопасные преобразования Под небезопасным преобразованием мы понимаем, что значение может быть неявно преобразовано в значение другого типа, не равное исходному значению. например: int я = 20000; символ с = я; Такие преобразования называются «сужающими» преобразованиями. double в int, char или bool int в char или bool char в bool   -  person Marichyasana    schedule 09.07.2018
comment
float char — еще один полезный тип, особенно в плавательных бассейнах. Некоторые комплектуются держателем для пива.   -  person Yakk - Adam Nevraumont    schedule 09.07.2018
comment
Это опечатка или допустимый синтаксис C++? Попробуйте (ОК, ОК, нет, это недействительно).   -  person Paul Sanders    schedule 09.07.2018
comment
@PaulSanders Но потом вы сталкиваетесь с такими вещами и думаете... что?   -  person Izkata    schedule 09.07.2018
comment
@Izkata Я не понимаю - это совершенно законно. Есть только предупреждение компилятора о неиспользуемой переменной.   -  person Paul Sanders    schedule 09.07.2018
comment
@PaulSanders Подумайте об этом с точки зрения новичка: он по-прежнему объединяет два типа данных, но по какой-то причине этот является законным. (Я не C++-er и понятия не имею, почему это законно и, например, это не )   -  person Izkata    schedule 10.07.2018
comment
@Izkata О, хорошо, я могу объяснить это тебе. long long — это отдельный тип данных в C/C++. В наши дни на практике это 64-битное целое число, даже на 32-битных платформах (целочисленные типы вообще немного беспорядочны, и сейчас их около 32767, потому что разработчики стандартов продолжают создавать новые без очевидной причины) .   -  person Paul Sanders    schedule 10.07.2018


Ответы (4)


В книге ошибка. Это недопустимое объявление C++, даже без предполагаемого сужающего преобразования.

Он не упоминается ни в одной из ошибок на странице Бьярна Страуструпа (4-е издание и ранее ), хотя, что странно. Это достаточно явная ошибка. Я предполагаю, что, поскольку он прокомментирован с //error, мало кто замечает ошибку в самом объявлении.

person StoryTeller - Unslander Monica    schedule 09.07.2018
comment
Какой, вероятно, был предполагаемый пример кода в книге? - person Pedro A; 10.07.2018
comment
@Hamsterrific char b1 {1000}; (потому что это спровоцирует ошибку, упомянутую в комментарии). Думаю, в тот день печатающие пальцы Бьярн устали. - person Paul Sanders; 10.07.2018
comment
@PaulSanders Устал? Он напечатал там лишнее int! :-) - person Lmn; 10.07.2018
comment
@ ЛеоХейнсар Лол. Хорошо, тогда слишком много кофе :) Или, может быть, он заикается :) - person Paul Sanders; 10.07.2018
comment
Ага: пальцы устали. Это похоже на ошибку вырезания и вставки из предыдущего примера. В предыдущем примере он дает две строки: int a {1000}; // OK [\n] char b {a} // ошибка: int -> char может сузить [\n], и он, кажется, вырезал и вставил этот пример для следующего и пропустил удаление части int: int символ b1 {1000}; // ошибка: сужение (при условии 8-битных символов) [\n] char b2 {48}; // ОК [\n] - person L. Scott Johnson; 13.07.2018

Книга неправильная.

Последовательность токенов int char b1{1000}; не является семантически допустимой C++.

Вы пытаетесь объявить b1 более чем с одним типом, что не имеет смысла.

person Bathsheba    schedule 09.07.2018

Это неверно. В C/C++ объявления нескольких типов могут быть реализованы с помощью объединений. Например:

union {
    int i;
    char c;
} var;

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

Хранилище то же самое, поэтому .c и .i являются просто дескрипторами одного и того же значения для каждого типа.

person Alex    schedule 10.07.2018

Это неправильно в синтаксисе C/C++. В дополнение к unions (см. ответ @Alex) существует способ C++ для хранения только одного из доступных типов, который называется std::variant (типобезопасное объединение):

#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
}
person val is still with Monica    schedule 13.07.2018