История соглашения о вызовах функций в C - PullRequest
0 голосов
/ 12 июня 2018

Как я помню, ранний C (например, K & R) позволял передавать что-либо при любом вызове функции, поэтому соглашение о вызовах должно было заключаться в том, что аргументы помещаются справа налево, и вызывающая сторона очищает стек после возврата функции.

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

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

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

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

Какова реальная ситуация в соответствии со стандартом?И какова история этого - она ​​изменилась со временем?

1 Ответ

0 голосов
/ 12 июня 2018

Стандарт C ничего не говорит о соглашениях о вызовах.

Начиная со стандарта ANSI C 1989 года (эквивалентного стандарту ISO C 1990 года), вызов функции с переменным числом, например printf без правильного объявления в области видимости, имеетнеопределенное поведение.Это объявление должно быть прототипом , и оно должно включать последовательность , ..., указывающую на то, что число переменных и тип (ы) аргументов принимаются.

Начиная с ISO C 1999 годастандартным является то, что вызов функции без видимого объявления является нарушением ограничения , требующим диагностики.(Это почти так же близко, как C доходит до утверждения, что конструкция недопустима.) До C99 вызываемая функция неявно объявлялась с типом возврата int, и любые (повышенные) аргументы появляются в вызове.

Многие компиляторы C будут принимать (возможно, с предупреждением) вызов без объявления, и многие, вероятно, используют соглашение о вызовах, которое делает вызов printf без видимого объявления «работа».Но язык не определяет поведение такого вызова, и соответствующий компилятор может отклонить его или сгенерировать код, который произвольно плохо себя ведет.

Если вы хотите вызвать printf, просто добавьте #include <stdio.h> вверху вашего исходного файла.Это намного проще, чем думать о том, что вам может сойти с рук для данного компилятора.

...