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

17

Я озадачен различием в поведении между 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

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

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

задан Josh Peterson 02.09.2014 в 16:36
источник
  • У меня такое чувство, что это изменилось в C ++ 11, чтобы дать более разумное поведение, которое вы видите выше, с clang - я уверен, что вскоре будет процитирован язык и стих ... –  Paul R 02.09.2014 в 16:39
  • @Paul R: «Нечувствительное» поведение существовало только в C89 / 90, где компилятору пришлось попробовать int, long int и unsigned long int. Включение неподписанного типа было плохим решением, которое было отменено в C099 и в самой первой версии C ++ (C ++ 98). Теперь компилятор должен попробовать только подписанные типы в порядке возрастания ширины. В этом случае единственным отличием C ++ 11 является добавление long long int. Это чисто количественный. –  AnT 02.09.2014 в 16:51
  • ОК - спасибо - может быть, я перепутался между C и C ++. FWIW Я всегда добавляю явный суффикс, так что никогда не задумывайтесь о том, как должно быть поведение. –  Paul R 02.09.2014 в 16:53

1 ответ

13

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

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

В 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 sequence).

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

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

    
ответ дан AnT 02.09.2014 в 16:40
  • Я думаю, что это зависит от того, компилируете ли вы C ++ 11 или нет? –  Paul R 02.09.2014 в 16:43
  • @Paul R: Как? Поскольку C ++ 98 «суффиксные» целые литералы должны были быть судимы для int и long int. В MSVC оба обычно имеют одинаковую ширину. –  AnT 02.09.2014 в 16:47
  • Командная строка, которую я использую для MSVC, - cl wat.cpp / EHsc, поэтому никаких специальных флагов, кроме одного для обработки исключений, нет. Я не думаю, что в MSVC есть флаг C ++ 11. –  Josh Peterson 02.09.2014 в 16:50
  • Я не эксперт по этому вопросу, но я думаю, что в течение последних нескольких дней был вопрос SO по этому самому вопросу - я посмотрю, смогу ли я его найти ... –  Paul R 02.09.2014 в 16:50
  • ОК - вот оно: stackoverflow.com/questions/25605777/... - Я, очевидно, думал о C, а не C ++ - извините за шум ... –  Paul R 02.09.2014 в 16:57
Показать остальные комментарии