Альтернативний (K&R) C синтаксис для оголошення функції порівняно з прототипами


76

Що корисного у цьому Cсинтаксисі - використання оголошень функції стилю 'K&R'?

Я зміг написати це у Visual Studios 2010beta

Я не розумію. Який сенс у цьому синтаксисі? Я можу написати:

Єдине, що, здається, вказує, скільки параметрів він використовує і тип повернення. Я думаю, параметри без типів - це якось круто, але навіщо це дозволяти і int paranNameпісля декларатора функції? Це дивно.

Також це все ще стандартний С?


Це старий стиль оголошень функцій. Перегляньте це посилання. /programming/22500/what-are-the-major-differences-between-ansi-c-and-kr-c текст посилання
Леонідас Цампрос

Відповіді:


154

Питання, яке ви задаєте, - це насправді два питання, а не одне. Більшість відповідей до цього часу намагалися охопити цілу річ загальною ковдрою "це стиль K&R", хоча насправді лише невелика частина цього має щось спільне з тим, що називається стилем K&R (якщо ви не бачите всю мову C як "K & R-style" в тій чи іншій мірі :)

Перша частина - це дивний синтаксис, який використовується у визначенні функції

Це насправді визначення функції у стилі K&R. Інші відповіді висвітлювали це досить добре. І насправді тут не так багато. Синтаксис застарілий, але все ще повністю підтримується навіть у C99 (за винятком правила "без неявного int" у C99, що означає, що в C99 ви не можете пропустити декларацію p2).

Друга частина має мало спільного із стилем K&R. Я маю на увазі той факт, що функцію можна викликати за допомогою "обмінених" аргументів, тобто у такому виклику не відбувається перевірка типу параметра. Це має дуже мало спільного з визначенням стилю K&R як таке, але воно має все спільне з вашою функцією, яка не має прототипу. Розумієте, в C, коли ви оголошуєте таку функцію

він фактично оголошує функцію, fooяка приймає невизначену кількість параметрів невідомого типу . Ви можете назвати це як

і як

і так далі (ви зрозуміли ідею);

Тільки дзвінок із належними аргументами буде "спрацьовувати" (це означає, що інші виробляють невизначену поведінку), але лише ви самі повинні забезпечити його правильність. Компілятор не повинен діагностувати неправильні, навіть якщо він якимось магічним чином знає правильні типи параметрів та їх загальну кількість.

Насправді така поведінка є особливістю мови C. Небезпечний, але тим не менше особливість. Це дозволяє зробити щось подібне

тобто змішувати різні типи функцій у "поліморфному" масиві без будь-яких наборів типів (тут, однак, різні типи функцій використовувати не можна). Знову ж таки, властиві цій техніці небезпеки є цілком очевидними (я не пам’ятаю, щоб коли-небудь використовував їх, але я можу уявити, де це може бути корисним), але це зрештою C.

Нарешті, біт, який пов'язує другу частину відповіді з першою. Коли ви робите визначення функції у стилі K & R, воно не вводить прототип для функції. Що стосується типу функції, ваше funcвизначення декларує funcяк

тобто не оголошуються ні типи, ні загальна кількість параметрів. У своєму оригінальному дописі ви говорите "... схоже, вказується, скільки параметрів він використовує ...". Формально кажучи, ні! Після вашого двопараметричного funcвизначення стилю K & R ви все ще можете телефонувати funcяк

і в ньому не буде жодних порушень обмежень. (Зазвичай якісний компілятор видасть вам попередження).

Крім того, часом пропускається факт, що це

також є визначенням функції у стилі K&R, яке не вводить прототип. Щоб зробити його "сучасним", вам потрібно було б вказати явний voidсписок параметрів

Нарешті, всупереч поширеній думці, як визначення функцій у стилі K & R, так і декларації функцій, що не є прототипами, повністю підтримуються в C99. Перший, як я пам’ятаю, застарів із C89 / 90. C99 вимагає, щоб функція була оголошена перед першим використанням, але декларація не повинна бути прототипом. Плутанина, очевидно, походить від популярного термінологічного змішування: багато людей називають будь-яку декларацію функції "прототипом", тоді як насправді "декларація функції" - це не те саме, що "прототип".


1
Але яка різниця зараз між функцією varargs та непрототипованою.
Себастьян

1
Варарги @Sebastian Godelet неминуче суворі. Наприклад, виклик функції vararg одним int, і виведення її як байтів є недійсним. Так само як і визначення функції лише з параметрами vararg.
yyny

Функції @Sebastian Vararg насправді можна правильно викликати з різною кількістю параметрів, наприклад printf. Функції без прототипів можна правильно викликати лише з певною фіксованою кількістю аргументів, але компілятор не знає, який з них і не може перевірити (тому ви повинні це зробити).
не користувач

Думаю, настав час змінитися supported even in C99. C99 to C11. :-).
sjsam

Я пам’ятаю, коли я починав з C на Amstrad PCW, я був розгублений, оскільки компілятор використовував старий синтаксис оголошення функції, але підручник, який я мав, використовував новий синтаксис. Це були часи ... 25 років тому ...!
Andrew Truckle

18

Це досить старий синтаксис K&R C (до дати ANSI / ISO C). Сьогодні вам більше не слід його використовувати (оскільки ви вже помітили його основний недолік: компілятор не перевіряє типи аргументів замість вас). Тип аргументу фактично є типовим intу вашому прикладі.

У той час цей синтаксис використовувався, іноді можна було знайти такі функції, як

який на самому справі є допустимим визначення, як типи для foo, pі по qзамовчуванням в int.


5

Це просто старий синтаксис, який попередньо датує синтаксис "ANSI C", з яким ви могли б бути більш знайомими. Зазвичай це називається " K&R C ".

Компілятори підтримують його повноту і, звичайно, можливість обробляти старі бази коду.


2

Це пережиток, коли C не мав прототипів функцій. Вже тоді, я думаю, функції поверталися, intі всі аргументи були такими int. Не було проведено перевірки параметрів функції.

Вам набагато краще використовувати прототипи функцій поточною мовою C.
І ви повинні використовувати їх у C99 (C89 все ще приймає старий синтаксис).

А C99 вимагає оголошень функцій (можливо, без прототипу). Якщо ви пишете нову функцію з нуля, вам потрібно надати декларацію ... зробіть її теж прототипом: ви нічого не втрачаєте і отримуєте додаткові перевірки від компілятора.


4
Невірно. У C99 функції повинні бути явно оголошені перед тим, як їх викликати. Nevertheles, C99 не вимагає проротипізованої декларації. C99 повністю підтримує синтаксис K&R з однією зміною: неявне intправило було видалено.
AnT

1

Це оригінальний синтаксис K&R до того, як C був стандартизований в 1989 році. C89 представив прототипи функцій, запозичені у C ++, і застарів синтаксис K&R. Немає причин використовувати його (і безліч причин не використовувати) у новому коді.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.