Обратите внимание, что я имею в виду именно объявление функции
синтаксис, а не использование непрототипированных функций.
Вы, кажется, играете немного быстро и свободно с языком. Я думаю, вы имеете в виду, что вы говорите о влиянии выбора функции определение синтаксис. Определения функций предоставляют объявления функций, и эти объявления могут (стиль ANSI) или не включать (стиль K & R), включая прототипы. Объявления функций, которые не являются частью определений (предварительные объявления), также могут предоставлять или не предоставлять прототипы. Важно понимать, что поведение немного отличается в зависимости от того, имеется ли прототип в области применения.
Многое было сделано о том, что прежний синтаксис не создает функцию
прототип. Мое исследование показывает, что если функция была определена как
выше, последующий вызов foo (8, 6, 7, 5, 3, 0, 9) приведет к
неопределенное поведение;
Да . Это вытекает из языковых ограничений (поэтому не только поведение не определено, но и нарушения должны быть диагностированы). В C11 соответствующий текст - пункт 6.5.2.2/2:
Если выражение, обозначающее вызываемую функцию, имеет тип, который
включает в себя прототип, количество аргументов должно быть согласовано с
количество параметров. Каждый аргумент должен иметь такой тип, чтобы его
значение может быть присвоено объекту с неквалифицированной версией
тип соответствующего параметра.
Обратите внимание, что речь идет о согласовании аргументов вызова функции с прототипом в области видимости, независимо от того, действительно ли прототип соответствует определению функции. (Но другие правила требуют, чтобы все объявления одного и того же типа функции, включая его определение, были совместимы.)
тогда как с последним синтаксисом foo (8, 6, 7, 5, 3,
0, 9) фактически будет недействительным.
Да ? Похоже, вы проводите различие, которое я не наблюдаю между тем, что является «недействительным», и тем, что имеет неопределенное поведение. Код, который является «недействительным» по любому определению, о котором я могу думать, определенно имеет неопределенное поведение. В любом случае, поведение в этом случае также явно не определено, так как при наличии прототипа в области действия 6.5.2.2/2 (см. Выше) применяется независимо от формы определения функции. Если имеется , а не прототип, находящийся в области применения, то вместо этого применяется пункт 6.5.2.2 / 6 (в C11). В нем говорится, частично:
Если выражение, обозначающее вызываемую функцию, имеет тип, который
не включает прототип [...] Если количество аргументов не
При равном количестве параметров поведение не определено.
Компилятор может не распознать или не диагностировать такую ошибку, и вы можете протестировать ее на какой-то конкретной реализации, не наблюдая никаких негативных последствий, но поведение определенно не определено, и при некоторых обстоятельствах в некоторых реализациях что-то сломается.
У меня такой вопрос: предполагается, что прототипы функций уже
при условии, является ли синтаксис K & R менее безопасным, чем стиль со встроенным
введите ключевые слова?
Если один и тот же прототип для функции f()
находится в области действия и там, где функция определена, и где она вызывается (хорошая практика в любом случае), и если определение стиля K & R для f()
задает тот же тип возврата и типы параметров, которые делает прототип, тогда все будет работать нормально. Несколько совместимых объявлений в области видимости в определении функции объединяются, чтобы сформировать составной тип для функции, который будет совпадать с типом, объявленным прототипом. Семантика точно такая, как если бы в определении использовался синтаксис ANSI напрямую. Об этом говорится в разделе 6.2.7 и соответствующих разделах стандарта.
Однако существует дополнительное бремя обслуживания в поддержании определения функции, которое не соответствует лексическому типу его прототипа.Также повышается вероятность ошибок, возникающих из-за того, что типы параметров в списке объявлений параметров не соответствуют прототипу, и в этом смысле подход менее безопасен, чем простое использование стиля ANSI.
Однако, если нетпрототип для f()
в области видимости в точке его определения в стиле K & R, и если какой-либо из его параметров имеет тип float
или целочисленные типы, меньшие чем int
, тогда существует больше возможностей для ошибки.Несмотря на объявленные типы параметров, реализация функции будет ожидать, что аргументы будут подвергнуты продвижению аргументов по умолчанию, и поведение не определено, если на самом деле это не так.Можно написать прототип, который предвидит эту потребность, для использования там, где вызывается f()
, но слишком легко ошибиться.В этом смысле предложенная вами комбинация действительно менее безопасна.