Как должен быть представлен 64-битный целочисленный литерал в С++?

Я озадачен различием в поведении между MSVC и clang для этого кода:

#include <iostream>
#include <cstdint>

int main() {
  int64_t wat = -2147483648;
  std::cout << "0x" << std::hex << wat << std::endl;

  return 0;
}

Visual Studio 2010, 2012 и 2013 (в Windows 7) отображаются все:

0x80000000

Но clang 503.0.40 (на OSX) отображает:

0xffffffff80000000

Какое правильное поведение соответствует стандарту С++? Должен ли литерал быть расширен с нулевым или расширенным значком до 64 бит?

Я знаю, что int64_t wat = -2147483648LL; приведет к такому же результату для обоих компиляторов, но я задаюсь вопросом о правильном поведении без литерального суффикса.

Ответы

Ответ 1

Тип слева от инициализации не имеет значения. Выражение -2147483648 интерпретируется само собой, независимо.

Литерал 2147483648 не имеет суффиксов, что означает, что компилятор сначала попытается интерпретировать его как значение int. На вашей платформе int, по-видимому, 32-битный тип. Значение 2147483648 выходит за пределы диапазона 32-битного целочисленного типа. Компилятор должен использовать более широкий тип целочисленного знака для представления значения, если он доступен (в последовательности int, long int, long long int, причем последний из них формально доступен из С++ 11). Но если не существует достаточно широкого целочисленного типа, поведение undefined

В MSVC исторически long int имеет ту же ширину, что и int, хотя 64-разрядная long long int также поддерживается в более поздних версиях MSVC. Однако даже в VS2013 (который поддерживает long long int) я получаю

warning C4146: unary minus operator applied to unsigned type, result still unsigned

в ответ на вашу инициализацию. Это означает, что MSVC по-прежнему придерживается архаичных правил C89/90 целочисленной литерала (где типы были выбраны из последовательности int, long int, unsigned long int).

Обратите внимание, что MSVC официально не является компилятором С++ 11. Так что формально это не нужно пробовать long long int. Такой тип формально не существует на языке pre-С++ 11. С этой точки зрения, MSVC не имеет достаточно большого знакового целочисленного типа для использования в этом случае, а поведение undefined. В пределах свободы, обеспечиваемой поведением undefined, использование правил C89/90 для цельной интерпретации буквально вполне оправданно.

Вы также можете взглянуть на это (- 2147483648 > 0) возвращает true в С++?