Продвигается ли char по умолчанию?
это может быть глупый вопрос, но кто-то может предоставить стандартную ссылку для C++11 и C11:
Is char
по умолчанию-назначен int
?
вот немного фона: оба C и C++ имеют понятия по умолчанию аргумент акции (C++11: 5.2.2/7; C11: 6.5.2.2/6). Это означает, что в следующем вызове аргументы продвигаются:
void f(int, ...);
float a = 1; short int b = 2; char c = 'x';
f(0, a, b, c);
для вызова функции, a
преобразуется в double
и b
превращается в int
. Но что происходит с c
? У меня всегда было впечатление, что char
также получает повышение до int
, но я не могу найти соответствующее заявление в стандартах.
2 ответов
C++
в C++ 2011 (ISO / IEC 14882: 2011) соответствующие части, похоже, следующие:
§5.2.2 вызов функции [expr.call]
¶6 функция может быть объявлена для принятия меньшего количества аргументов (путем объявления аргументов по умолчанию (8.3.6)) или более аргументы (с помощью многоточия, ..., или пакет параметров функции (8.3.5)), чем количество параметров в определении функции (8.4). [Примечание: это означает, что, за исключением того, где многоточие (...) или функция используется пакет параметров, для каждого аргумента доступен параметр. - конец Примечания]
¶7 когда для данного аргумента нет параметра, аргумент передается таким образом, что получающий функция может получить значение аргумента, вызвав va_arg (18.10). [Примечание: данный пункт не содержит применить к аргументам, переданным в пакет параметров функции. Пакеты параметров функции расширяются во время инстанцирование шаблона (14.5.3), таким образом, каждый такой аргумент есть соответствующий параметр, когда функция специализация шаблона фактически называется. - Примечание конца] lvalue-к-rvalue (4.1), массив-к-указатель (4.2), и стандартные преобразования функции в указатель (4.3)выполняются для выражения аргумента. Аргумент, что имеет (возможно, CV-квалифицированный) тип std:: nullptr_t преобразуется в тип void* (4.10). После этих преобразований, если аргумент не имеет арифметики, перечисления, указателя, указателя на элемент или тип класса, то программа плохо сформирована. Передача потенциально оцениваемого аргумента типа класса (пункт 9), имеющего нетривиальный конструктор копирования, нетривиальный ход подрядчиком, или нетривиальный деструктор, без соответствующего параметр, условно-поддерживается с семантикой, определенной реализацией.
если аргумент имеет Интеграл или тип перечисления, подлежащий интегральному продвижению (4.5), или тип с плавающей запятой, подлежащий к акции с плавающей запятой (4.6), значение аргумент преобразуется в тип promoted до вызов. Эти акции называются промо-акциями по умолчанию.
я разделил последние два предложения, чтобы подчеркнуть их. Они являются неотъемлемой частью пункта 7 стандарта.
§4.5 интегральные рекламные акции [conv.пром]
¶1 значение целого типа, отличное от
bool
,char16_t
,char32_t
илиwchar_t
преобразования, целочисленное ранг (4.13) меньше, чем рангint
можно преобразовать в prvalue типаint
еслиint
могут представлять все значения исходного типа; в противном случае исходное значение prvalue может быть преобразовано в значение prvalue типаunsigned int
.¶2 prvalue типа
char16_t
,char32_t
илиwchar_t
(3.9.1) можно преобразовать в prvalue первого из следующие типы, которые могут представлять все значения базового типа:int
,unsigned int
,long int
,unsigned long int
,long long int
, илиunsigned long long int
. Если ни один из типов в этом списке не может представляют все значения его базового типа, prvalue типаchar16_t
,char32_t
илиwchar_t
может быть преобразуется в prvalue базового типа.
Etc.
C
C имеет два контекста, в которых аргументы по умолчанию продвигаются. Первый - когда в области видимости функции нет прототипа (первый покрыт другим ответом), а второй-когда есть прототип с многоточием. Конечно, C++ вообще не допускает первого случая. Эти цитаты взяты из тех же разделов стандарта, что и другой ответ, но фрагменты здесь несколько длиннее. Они были найдены независимым анализом стандарта, и только при перекрестной проверке я заметил, что сечения одинаковы.
в C 2011 (ISO / IEC 9899: 2011) соответствующие части, похоже, являются:
функции§6.5.2.2 называет
¶6 Если выражение, обозначающее вызываемую функцию, имеет тип, который не включает prototype, целочисленные рекламные акции выполняются для каждого аргумента и аргументов, которые у типа float повышаются до double. Они называются аргументом по умолчанию специальные акции. Если число аргументов не равно числу параметров, то поведение не определено. Если функция определена с типом, который включает прототип, и либо прототип заканчивается многоточием (
, ...
) или типы аргументы после продвижение не совместимо с типами параметров, поведение не определено. Если функция определена с типом, который не включает прототип, и типами аргументы после продвижения не совместимы с аргументами параметров после поощрения, поведение не определено, за исключением следующих случаев:- один повышенный тип является целочисленным типом со знаком, другой повышенный тип соответствующий беззнаковое целое type, и значение представляется в обоих типах;
- оба типа являются указателями на квалифицированные или неквалифицированные версии символьного типа или пустота.
¶7 если выражение, обозначающее вызываемую функцию, имеет тип, который включает прототип, аргументы неявно преобразуются, как если бы путем присвоения, в типы соответствующих параметров, принимая тип каждого параметра, чтобы быть объявленного типа. Этот многоточие нотации в деклараторе прототипа функции вызывает преобразование типа аргумента в stop после последнего объявленного параметра. Аргумент по умолчанию акции проводятся по аргументам трейлинга.
"целочисленные акции" определены в §6.3.1.1:
§6.3.1 арифметических операндов
§6.3.1.1 логическое, символы и целые числа
¶1 Каждый целочисленный тип имеет целочисленный ранг преобразования, определенный как следует:
- никакие два целочисленных типа со знаком не должны иметь одинаковый ранг, даже если они имеют одинаковый представление.
- ранг знакового целочисленного типа должен быть больше ранга любого знакового целого числа печатайте с меньшей точностью.
- ранг long long int должен быть больше, чем ранг long int, который должно быть больше ранга int, который должен быть больше ранга short int, который должен быть больше ранг подписанного char.
- ранг любого целочисленного типа без знака должен равняться рангу соответствующего целочисленный тип со знаком, если таковой имеется.
- ранг любого стандартного целочисленного типа должен быть больше ранга любого расширенного целочисленный тип с одинаковой шириной.
- ранг char равен рангу подписанного char и неподписанного char.
- ранг _Bool должен быть меньше, чем ранг всех других стандартов целочисленный тип.
- ранг любого перечисляемого типа должен равняться рангу совместимого целочисленного типа (см. 6.7.2.2).
- ранг любого расширенного знакового целочисленного типа относительно другого расширенного знака целочисленный тип с той же точностью определяется реализацией, но все еще подлежит другие правила определения ранга преобразования целых чисел.
- для всех целых типов T1, T2 и T3, если T1 имеет больший ранг, чем T2 и T2 имеет более высокий ранг, чем Т3, то Т1 имеет более высокий ранг, чем Т3.
¶2 в выражении, где
int
илиunsigned int
может быть использованы:- объект или выражение с целочисленным типом (кроме
int
илиunsigned int
) чей целочисленный ранг преобразования меньше или равен рангуint
иunsigned int
.- бит-поле типа
_Bool
,int
,signed int
илиunsigned int
.если Ан
int
может представлять все значения исходного типа (ограниченные шириной, для bit-field), значение преобразуется вint
; в противном случае он превращается вunsigned int
. Они называются целое число акций.58) все другие типы неизменны целочисленные акции.58) целочисленные акции применяются только: как часть обычных арифметических преобразований, к определенным аргумент выражения для операндов унарных операторов +, -, и ~ и для обоих операндов операторы сдвига, как указано в соответствующих подпунктах.
отмечу, что в свое время в вопросе перечислялась функция void f(...);
, который является функцией C++, а не функцией C; C не позволяет многоточию отображаться как единственный аргумент функции. С тех пор вопрос был обновлен до void f(int, ...);
который действителен как на C, так и на C++.
во-первых, по умолчанию аргумент promotions
6.5.2.2
если выражение, обозначающее вызываемую функцию, имеет тип, который не включает прототип,целое число акций выполняются по каждому аргументу и аргументы с типом float повышены в два раза. Они называются аргумент по умолчанию акции.
Теперь для integer акции:
6.3.1.1
в выражении, где int или unsigned может использоваться следующее int может использоваться:
- объект или выражение с целочисленным типом (кроме int или unsigned int), чей целочисленный ранг преобразования меньше или равно рангу int и unsigned int.
Если int может представить все значения исходного типа (Как ограничено по ширине, для bit-field), значение преобразуется в int; в противном случае он преобразуется в unsigned int. Они называются целое число акций.
Так что для C по крайней мере a char
по умолчанию-назначен int
или unsigned int
.