Постоянные целочисленные правила продвижения?

чтобы дать небольшой фон (не связанный с вопросом, который последует), в C++11 я заметил сужающуюся проблему:

int foo[] = { 0xFFFFFFFF };

это не удалось скомпилировать (сужение преобразования), потому что 0xFFFFFFFF это unsigned int. Однако я видел случаи, когда - это.

Я просмотрел целочисленные правила продвижения, но это в основном в контексте lvalues, а не rvalues / constants. Как компилятор определяет тип констант (без литерала суффиксы)? Есть ли документация или хорошая маленькая таблица / "шпаргалка", которая показывает правила для этого? Я даже не знаю, как это называется, иначе я бы попытался найти его сам в стандарте C++11.

спасибо заранее.

3 ответов


в стандарте есть таблица, которая воспроизводится на cppreference.com:http://en.cppreference.com/w/cpp/language/integer_literal

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

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

0xFFFFFFFF слишком большой для int Если int имеет длину 32 бита, поэтому это. Но!--5--> удобно помещается в int, так что int это.


то, что называетсяцелочисленные константы в C называются целочисленные литералы в C++. Правила, используемые для определения типа целочисленный литерал охватывает проект стандарта C++ раздел 2.14.2 целочисленные литералы стол 6 Он говорит:

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

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

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

так 0xFF может быть представлен как int в то время как первый тип, который может представлять 0xFFFFFFFF будет unsigned int.

порядок Десятичные Константы следующим образом:

int
long int
long long int

как мы видим, шестнадцатеричную и восьмеричные литералы ведут себя по-разному, и мы видим что C99 имеет ту же таблицу. The обоснование международного стандарта-языки программирования-C говорит об этом так:

в отличие от десятичных констант, восьмеричных и шестнадцатеричных констант, слишком больших, чтобы be ints вводятся как unsigned int, если в пределах этого типа, так как более вероятно, что они представляют собой битовые маски или маски, которые как правило, лучше всего рассматривать как неподписанный, вместо "реальных" чисел.

cppreference целочисленный литерал разделе также цитирует таблице 6 на тип литерала подраздел.


0xFF никогда не бывает отрицательным. Это альтернативный способ написания 255. (Типа int).

0xFFFFFFFF является большим положительным числом. Есть таблица под [lex.icon], который определяет тип целочисленной константы. Для шестнадцатеричных констант без суффикса это первый тип в следующем списке, который может содержать это большое положительное число:int, unsigned int, long int, unsigned long int, long long int, unsigned long long int. Реализация может добавить пользовательские типы OT это список.