2013-08-24 3 views
10

Я не знаком с K & Объявление функции стиля R.Объявление функции C в K & R

После компиляции с предупреждением (только что связанное с возвращаемым значением main, которое тоже с -Wall), но каковы используемые типы данных переменных?

main(a, b, c, d){ 
    printf("%d", d); 
} 

foo(a, b){ 
    a = 2; 
    b = 'z'; 
} 

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

Редактировать

Я просто наткнулся на запутанном код C, который использует их.
Но могу вас заверить, я не буду использовать такой синтаксис в программировании на языке C.

+2

Каковы предупреждения, которые вы получаете? Было бы полезно попытаться ответить на ваш вопрос. – Glenn

+0

@Glenn Извините, никаких предупреждений, связанных с типами – P0W

+0

Бонус: попробуйте вызвать 'foo (« this »,« should not »,« work »)'. – nneonneo

ответ

19

«K & R C» относится к языку, определенному в 1978 году первым изданием Kernighan & Книга Ричи «Язык программирования C».

В K & R (то есть, pre-ANSI) C объекты могут быть объявлены без явного типа и по умолчанию будут иметь тип int. Это восходит к языкам предков C, B и BCPL.

main(a,b,c,d){ 
    printf("%d", d); 
} 

Это почти эквивалентно:

int main(int a, int b, int c, int d) { 
    printf("%d", d); 
} 

старый синтаксис остается легальным, но устаревшее в ANSI C (1989) и ISO C (1990), но стандарт 1999 ISO C выронил " неявное int "(при сохранении декларации старого стиля и синтаксиса определения).

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

И поскольку это определение main, есть еще одна проблема. Стандарт определяет только две формы для main (один без аргументов и один с двумя аргументами, argc и argv). Реализация может поддерживать другие формы, но одна из четырех аргументов int вряд ли будет одной из них. Поэтому поведение программы не определено. На практике, вероятно, что d будет иметь некоторую стоимость мусора при первоначальном вызове.(И да, рекурсивный вызов main разрешено в C, но вряд ли когда-либо хорошая идея.)

foo(a,b){ 
    a = 2; 
    b = 'z'; 
} 

Это почти эквивалентно:

int foo(int a, int b) { 
    a = 2; 
    b = 'z'; 
} 

(И заметьте, что 'z' имеет тип int, а не тип char)

И снова, старая форма не дает вам параметры проверки типа, поэтому вызов, как:.

foo("wrong type and number of arguments", 1.5, &foo); 

не нужно диагностировать.

Практический результат: полезно знать, как K & Значения функций и определения функций R-стиля. Есть еще старый код, который их использует, и они все еще легальны (но устаревают) даже в C2011 (хотя без правила «неявного int»). Но нет почти никаких оснований, чтобы написать код, который использует их (если вы застряли, используя очень старый компилятор, но это редко и становится более редким.)

Но я могу заверить вас, я не буду использовать такой синтаксис в программировании на языке C.

Отлично!

3

В C89 значением переменной по умолчанию является int: он определяется как неявный int. Это правило было отменено на C99.

В вашем примере, она скомпилирована как:

main(int a,int b,int c,int d){printf("%d", d);} 

foo(int a,int b){a=2; b='z';} 
+3

Ну, почти. Фактически, он скомпилирован как «main (a, b, c, d) int a, b, c, d;'. Разница тонкая, но с синтаксисом K & R вы можете делать немые вещи, такие как вызов любой из этих функций с любым числом и типом параметров без предупреждений (см., Например, http://stackoverflow.com/q/18202232/1204143) – nneonneo

+0

Любое оправдание для этого 'foo (a, b, c) {printf ("% s-% s-% s ", a, b, c); } main (a, b, c, d) {foo ("this", "should not", "work");} 'Это просто работает. – P0W

+0

@ P0W Ваш фрагмент кода segfaults, когда я пытался его скомпилировать и запустить. Это сработало для вас? – aymericbeaumet

3

параметр по умолчанию ИНТ типа в C и K о синтаксисе & R пожалуйста посмотреть here и here.

6

В K & Определение функции стиля R тип параметра задается специальным набором объявлений, который помещается между самой функцией «подпись» и фактическим телом функции. Например, это определение функции

void foo(a, b, c) 
double a; 
char b; 
{ 
    ... 
} 

использует параметры типа double, char и int. Это на самом деле то, где и как действует правило «неявное int»: поскольку параметр c не упоминался в приведенном выше списке объявлений, предполагается, что он имеет тип int.

Обратите внимание на важную деталь, которая, как я полагаю, недостаточно прояснена другими ответами: параметр c имеет тип int не потому, что тип отсутствует в списке параметров функции, а скорее потому, что он не упоминается в последовательности деклараторов, что следует функция «подпись» (перед телом функции). В K & Типы деклараций типа R всегда отсутствуют в списке параметров функций (это определяющая особенность объявления K & R), но это не означает, что все параметры, как предполагается, имеют тип int.

P.S. Обратите внимание, что C99 по-прежнему поддерживает K & R-стилевые объявления, но поскольку C99 объявила вне закона «неявное int», вам необходимо указать все параметры функции в этом списке объявлений после функции «подпись». Приведенный выше пример не будет компилироваться на C99 по этой причине. int c должен быть добавлен в список объявлений.

+0

+1 Спасибо за последнее разъяснение. Не могли бы вы привести пример, где 'int' не предполагается по умолчанию? – P0W

+0

@ P0W: Я не уверен, что вы имеете в виду. То, что я говорю в своем ответе, заключается в том, что в приведенном выше примере 'b' НЕ считается' int' просто потому, что его тип отсутствует в списке параметров функции. Чтобы определить тип 'b', вместо того, чтобы перейти к непосредственным выводам, компилятор будет продолжать смотреть дальше. Он откроет объявление 'char b' и поймет, что' b' должен быть 'char'. – AnT

Смежные вопросы