На языке C компилятор выполняет продвижение аргумента по умолчанию когда вызываемая функция не имеет прототипа.
Но как насчет C ++? Когда произойдет продвижение по умолчанию для аргументов?
В C ++ 11 стандарт 5.2.2 / 7:
Если для данного аргумента нет параметра, аргумент
передается таким образом, что принимающая функция может получить значение
аргумента путем вызова va_arg (18.10). [Примечание: этот абзац
не применяется к аргументам, переданным в пакет параметров функции.
Пакеты параметров функций расширяются во время создания шаблона
(14.5.3), таким образом, каждый такой аргумент имеет соответствующий параметр, когда
Функция шаблона специализации на самом деле называется. — Конец примечания] lvalue-to-rvalue (4.1), массив-указатель (4.2) и
стандартное преобразование функции в указатель (4.3) выполняется на
выражение аргумента. Аргумент, который имеет (возможно, cv-квалифицированный) тип
std :: nullptr_t преобразуется в тип void * (4.10). После этих
преобразования, если аргумент не имеет арифметики, перечисления,
указатель, указатель на член или тип класса, программа плохо сформирована.
Передача потенциально оцениваемого аргумента типа класса (раздел 9)
имеющий нетривиальный конструктор копирования, нетривиальный конструктор перемещения,
или нетривиальный деструктор, без соответствующего параметра,
условно поддерживается с определенной семантикой реализации. Если
Аргумент имеет целочисленный тип или тип перечисления, который подчиняется
интегральное продвижение (4.5) или тип с плавающей запятой, который подлежит
продвижение с плавающей запятой (4.6), значение аргумента
преобразуется в повышенный тип до вызова. Эти акции
упоминается как продвижение аргумента по умолчанию.
Этот параграф все еще не определяет, когда произойдет продвижение аргумента по умолчанию. Этот абзац может говорить слишком много без четкой логики. Я попытался обрисовать логику, но не смог. Я не знаком с вызывая va_arg.
Надеюсь, ты поможешь мне.
Продвижение по умолчанию будет происходить до вызова функции в контексте вызова.
Если вы действительно спрашиваете об обстоятельствах, при которых проводятся промо-акции по умолчанию, это описано в отрывке, хотя это такой маленький кусочек, что его легко пропустить: «Когда для данного аргумента нет параметра …». Другими словами, это по сути идентично ситуации в C, за исключением того, что объявление функции в стиле C, которое не указывает типы параметров, просто не существует в C ++. Таким образом, единственный раз, когда вы можете иметь аргумент без параметра, указывающего его тип, это когда функция имеет явный многоточие, такое как printf
: int printf(char const *format, ...);
,
Из самого абзаца, который вы цитируете в своем вопросе: «Значение аргумента перед вызовом преобразуется в повышенный тип».
Вы говорите о C «продвижение аргумента по умолчанию, когда вызываемая функция не имеет прототипа» — но помните, что сценарий не существует в C ++ — вы не можете вызвать функцию, для которой не было обнаружено ни объявления, ни определения.
Упоминание «invoking va_arg» означает, что некоторые из продвижений аргументов применяются при вызове функции, которая затем получит доступ к значениям, используя va_arg
функции (см. http://linux.die.net/man/3/va_arg). Думайте об этом так: один вызов функции может передать значение int(3)
, другой int(7777)
, еще один char(7)
— как вызываемая функция должна знать, чего ожидать? Вероятно, он переведет все значения этого параметра в некоторый тип с наибольшим поддерживаемым интегралом, такой как int
или же long
, тогда, когда va_arg
используется в функции, из которой он будет конвертироваться int
или же long
к любому интегральному типу va_arg
звонок уточняет. Это означает, например, что int(7777)
значение может быть передано, где только char
ожидается, и значение может быть усечено до 8 бит без предупреждения, но это, как правило, лучше, чем аварийное завершение программы, поскольку количество переданных байтов данных не соответствует потребляемому количеству, или какой-то другой странный побочный эффект.