Объявление функций C в K & R

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

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

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

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

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

Edit

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

Ответ 1

"K & R C" относится к языку, определенному в 1978 году в первом издании книги Кернигана и Ричи "Язык программирования 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), но в стандарте ISO C 1999 года было исключено правило "неявное int" (при сохранении декларации старого стиля и синтаксиса определения).

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

И поскольку это определение main, есть еще одна проблема. Стандарт определяет только две формы для main (один без аргументов и один с двумя аргументами, argc и argv). Реализация может поддерживать другие формы, но один с четырьмя аргументами int вряд ли будет одним из них. Поэтому поведение программы undefined. На практике вероятно, что 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.

Отлично!

Ответ 2

В определении функции стиля 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 должен быть добавлен в список объявлений.

Ответ 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';}

Ответ 4

Параметр по умолчанию для типа int в C и синтаксис K и R, пожалуйста, посмотрите здесь и здесь.