Подтвердить что ты не робот

Можно ли полностью игнорировать вариационные аргументы функции C?

У меня есть функция, которая примерно выглядит так:

typedef struct SomeType {
  ...
} SomeType;

void TakesArgs(SomeType *t1, ...) {
     // iterates through arguments
}

// usage:
TakesArgs(&a, &b, &c);

Выполнять ли какие-либо странные риски с памятью (или иначе), если я должен изменить TakesArgs на no-op, оставив все код вызова без изменений?

void TakesArgs(SomeType *t1, ...) {
    return;
}

// usage unchanged: 
TakesArgs(&a, &b, &c);

Другими словами, пропустив танец va_list/va_start, который был выполнен в оригинальной реализации, есть какие-то странные побочные эффекты?

4b9b3361

Ответ 1

Да, это абсолютно безопасно. Вы не обязаны читать все вариативные аргументы только ради их чтения. Вам не требуется даже запускать последовательность чтения вариационных аргументов внутри TakesArgs.

Под капотом это обычно означает, что бремя выполнения любых задач, связанных с передачей аргументов, предоставляется коду вызова (они работают так, как обычно признается "традиционным" соглашением о вызове C). Вызов не должен ничего делать.

Ответ 2

Я считаю, что это безопасно, хотя стандарт не совсем ясен в этом вопросе.

N1570 7.16 в пункте 3 говорится:

Если требуется доступ к переменным аргументам, вызываемая функция объявляет объект (обычно называемый ap в этом подраздел) с типом va_list.

Обратите внимание на начало этого предложения: " Если требуется доступ к переменным аргументам". Подразумевается, что если доступ к переменным аргументам нежелателен, нет необходимости объявлять объект va_list, из-за чего невозможно вызвать va_start, va_arg или va_end.

Возможный контраргумент заключается в том, что описание va_end (N1570 7.16.1.3) гласит:

Если нет соответствующего вызова va_start или va_copyмакроса или если макрос va_end не вызывается перед возвратом, поведение не определено.

Однако, учитывая контекст, я считаю, что применяется, если va_end не вызывается после вызова va_start.

Ответ 3

[Отредактировано в ответ на комментарии.]

Существуют системы, в которых по умолчанию заданием вызываемого абонента является поп-аргумент. Это, очевидно, вызовет у вас неприятности. Но именно по этой причине переменные функции должны быть должным образом объявлены, и объявление должно быть правильно видимым для вызывающих. Причина в том, что в этих системах переменные функции должны использовать нестандартную вызывающую последовательность, в которой вызывающий пользователь выдает аргументы, потому что только вызывающий может быть уверен, сколько их есть. Поэтому вы должны быть в безопасности, пока ваши функции будут правильно объявлены.