Является ли char стандартным?

Это может быть глупый вопрос, но кто-то может предоставить стандартную ссылку для С++ 11 и C11:

Является ли char стандартным для int?

Здесь немного предыстории: и 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, но я не могу найти соответствующее утверждение в стандартах.

Ответы

Ответ 1

С++

В С++ 2011 (ISO/IEC 14882: 2011) соответствующие части выглядят следующим образом:

§5.2.2 Функциональный вызов [expr.call]

¶6 Функция может быть объявлена ​​для принятия меньших аргументов (путем объявления аргументов по умолчанию (8.3.6)) или более аргументы (используя эллипсис,... или пакет параметров функций (8.3.5)), чем количество параметров в определении функции (8.4). [Примечание: это означает, что, кроме случаев, когда многоточие (...) или функция Параметр используется, параметр доступен для каждого аргумента. -end note]

¶7 Если параметр для данного аргумента отсутствует, аргумент передается таким образом, что принимающий функция может получить значение аргумента, вызвав va_arg (18.10). [Примечание: этот абзац не применяются к аргументам, переданным в пакет параметров функции. Пакеты параметров функций расширяются во время (14.5.3), поэтому каждый такой аргумент имеет соответствующий параметр, когда функция на самом деле называется специализация шаблона. -end note] Значение lvalue-to-rvalue (4.1), массив-указатель (4.2) и Стандартное преобразование функции-to-pointer (4.3) выполняется по выражению аргумента. Доказательство того, что имеет (возможно, cv-qualified) тип std:: nullptr_t преобразуется в тип void * (4.10). После этих преобразований, если аргумент не имеет арифметики, перечисления, указателя, указателя на член или тип класса, программа плохо сформирована. Передача потенциально оцененного аргумента типа класса (раздел 9), имеющего нетривиальный конструктор копирования, нетривиальный конструктор перемещения или нетривиальный деструктор, без соответствующих параметр, условно поддерживается семантикой, определенной реализацией.

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

Я разделил последние два предложения, чтобы подчеркнуть их. Они являются неотъемлемой частью параграфа 7 стандарта.

§4.5 Интегральные акции [conv.prom]

¶1 Prvalue целочисленного типа, отличного от bool, char16_t, char32_t или wchar_t, целочисленное преобразование ранг (4.13) меньше ранга int может быть преобразован в prvalue типа int, если int может представлять все значения типа источника; в противном случае исходное prvalue может быть преобразовано в prvalue типа unsigned int.

¶2 Значение типа 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. Если ни один из типов в этом списке не может представляют все значения своего базового типа, значение типа char16_t, char32_t или wchar_t может быть преобразуется в prvalue своего базового типа.

Etc.


С

C имеет два контекста, в которых аргументы поддерживаются по умолчанию. Один из них заключается в отсутствии прототипа для функции (сначала охватываемой другим ответом), а во втором - прототипа с многоточием. Конечно, С++ не позволяет сделать первый случай. Эти цитаты из тех же разделов стандарта, которые выбраны другим ответом, но фрагменты здесь несколько длиннее. Они были найдены независимым анализом стандарта, и только при перекрестной проверке я заметил, что разделы одинаковы.

В C 2011 (ISO/IEC 9899: 2011) соответствующие части выглядят следующим образом:

§6.5.2.2 Функциональные вызовы

¶6 Если выражение, которое обозначает вызываемую функцию, имеет тип, который не включает прототип, целые рекламные акции выполняются для каждого аргумента и аргументы, которые имеют тип float, которые удваиваются. Они называются аргументом по умолчанию Акции. Если число аргументов не равно числу параметров, поведение undefined. Если функция определена с типом, который включает прототип, и либо прототип заканчивается эллипсисом (, ...), либо типом аргументов после продвижение не совместимо с типами параметров, поведение undefined. Если функция определена с типом, который не включает прототип, а типы аргументы после продвижения по службе не совместимы с параметрами после продвижение, поведение undefined, за исключением следующих случаев:

- один продвинутый тип представляет собой целочисленный тип со знаком, другой продвинутый тип - это соответствующий беззнаковый целочисленный тип, и значение представляется в обоих типах;

- оба типа являются указателями на квалифицированные или неквалифицированные версии типа символа или недействительна.

¶7 Если выражение, которое обозначает вызываемую функцию, имеет тип, который включает прототип, аргументы неявно преобразуются, как бы при назначении, типам соответствующие параметры, считая тип каждого параметра неквалифицированной версией его объявленного типа. Обозначение многоточия в объявлении прототипа функции вызывает преобразование типа аргумента для остановки после последнего объявленного параметра. Аргумент по умолчанию рекламные акции выполняются по завершающим аргументам.

"Целевые акции" определены в разделе 6.3.1.1:

§6.3.1 Арифметические операнды

§6.3.1.1 Булев, символы и целые числа

¶1 Каждый целочисленный тип имеет целочисленный ранг преобразования, определяемый следующим образом:

- Нет двух знаковых целочисленных типов, имеющих одинаковый ранг, даже если они имеют одинаковый представление.

- Ранг целочисленного типа со знаком должен быть больше ранга любого знакового целого числа тип с меньшей точностью.

- Ранг long long int должен быть больше ранга long int, который должен быть больше ранга int, который должен быть больше ранга короткого int, который должен быть больше ранга подписанного char.

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

- Ранг любого стандартного целочисленного типа должен быть больше ранга любого расширенного целочисленный тип с той же шириной.

- Ранг char должен равняться рангам подписанных char и unsigned char.

- Ранг _Bool должен быть меньше ранга всех других стандартных целых типов.

- Ранг любого перечисленного типа должен равняться рангам типа совместимого целого типа (см. 6.7.2.2).

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

- для всех целых типов T1, T2 и T3, если T1 имеет больший ранг, чем T2, а T2 имеет больший ранг, чем T3, то T1 имеет больший ранг, чем T3.

¶2 В выражении могут использоваться следующие выражения: int или unsigned int:

- объект или выражение с целым типом (кроме int или unsigned int) чей целочисленный ранг преобразования меньше или равен рангам int и unsigned int.

- бит-поле типа _Bool, int, signed int или unsigned int.

Если int может представлять все значения исходного типа (ограниченные шириной, для a бит-поле), значение преобразуется в значение int; в противном случае он преобразуется в unsigned int. Они называются целыми рекламными акциями. 58) Все остальные типы не изменяются целые рекламные акции.

58) Целые поощрения применяются только: как часть обычных арифметических преобразований, к определенным аргументов выражения, в операнды унарных операторов +, - и ~ и обоих операндов операторов сдвига, как указано в их соответствующих подпунктах.


Замечу, что в один момент вопрос перечислил функцию void f(...);, которая является функцией С++, а не C-функцией; C не позволяет эллипсису отображаться как единственный аргумент функции. С тех пор вопрос обновлен до void f(int, ...);, который действителен как в C, так и в С++.

Ответ 2

Во-первых, промо-акции по умолчанию

6.5.2.2

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

Теперь для целых рекламных акций:

6.3.1.1

В выражении могут использоваться следующие выражения: int или unsigned int может использоваться:

  • Объект или выражение с целым типом (кроме int или unsigned int), чей целочисленный ранг преобразования меньше или равен равный ранга int и unsigned int.

Если int может представлять все значения исходного типа (как ограниченные по ширине, для бит-поля), значение преобразуется в int; в противном случае он преобразуется в unsigned int. Они называются целые рекламные акции.

Итак, для C по крайней мере a char по умолчанию поддерживается int или unsigned int.