Использование целочисленных литералов в списке инициализаторов C ++ - PullRequest
2 голосов
/ 28 октября 2019

Я пытаюсь понять весь спектр функций синтаксиса инициализатора {} .

Я скомпилировал следующий код с g ++:

int i = 0;                /* OK */

short int si2 {i};        /* Warning: Narrowing Conversion inside {...} */

char myChar {127ULL};     /* OK */

char myChar2 {128ULL};    /* Warning: Narrowing Conversion inside {...} */

Мое понимание предупреждения об инициализации si2 следующее. В моей системе: - short int - 2 байта - int - 4 байта

Поскольку инициализатор в два раза больше (в байтах), чем LHS, это составляетсужение и, следовательно, предупреждение компилятора.

Однако для myChar и myChar2 оба инициализатора имеют одинаковый тип данных: unsigned long long int . Я считаю, что инициализация myChar2 произошла из-за того, что значение инициализатора было бы слишком большим для типа данных char .

те же правила, похоже, не применяютсяв обоих этих случаях: 1. Сбой из-за того, что тип инициализатора слишком велик для инициализированной переменной 2. Сбой из-за того, что значение слишком велико для инициализированной переменной (хотя тип данных RHS здесь допустим)

Правильно ли мое понимание здесь - верно лиСписок инициализаторов ведет себя иначе, если аргумент является целочисленным литералом?

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

Кажется, ваш компилятор по умолчанию считает тип char аналогично типу signed char.

В этих объявлениях

char myChar {127ULL};     /* OK */

char myChar2 {128ULL};

инициализаторы имеют положительные значения и положительное значение128 не может быть представлен в объекте со знаком типа char.

Максимальное положительное значение, которое может быть представлено типом со знаком char, равно 127. Это диапазон значений [-128, 127].

, поэтому компилятор выдает предупреждение.

Для этого оператора

short int si2 {i}; 

компилятор выдает предупреждение, поскольку инициализатор не является константой времени компиляции.

Если вы напишите

const int i = 0;

, то предупреждение исчезнет.

0 голосов
/ 28 октября 2019

Запомните это.

При использовании с переменными встроенного типа, эта форма инициализации имеет одно важное свойство: компилятор не позволяет нам перечислять переменные встроенного типа, если инициализатор можетпривести к потере информации:

    long double ld = 5.14159265;
    int a{ld}, b = {ld}; // error: narrowing conversion required
    int c(ld), d = ld; // ok: but value will be truncated

Компилятор отклоняет инициализации a и b, потому что использование long double для инициализации int может привести к потере данных. Как минимум, дробная часть ld будет усечена. Кроме того, целочисленная часть в ld может быть слишком большой, чтобы поместиться в int.

Теперь перейдем к последним 2 частям. Вы определили char , который имеет тип со знаком. Он может содержать значения от -128 до 127. Но вы пытаетесь назначить 128, и вы получили предупреждение от компилятора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...