Почему пустое объявление работает для определений с аргументами int, но не для аргументов float?

Я думал, что разница в том, что declaration не имеет типов параметров...

Почему это работает:

int fuc();

int fuc(int i) {
  printf("%d", i);
  return 0;
}

но это не скомпилируется:

int fuc();

int fuc(float f) {
  printf("%f", f);
  return 0;
}

с сообщением:

ошибка: конфликтующие типы для 'fuc. note: тип аргумента, который по умолчанию не поддерживает продвижение по службе, соответствует объявлению списка пустых параметров

Ответ 1

Объявление:

int f();

... сообщает компилятору, что некоторый идентификатор (f в этом случае) называет функцию и сообщает ему тип возвращаемого значения функции - но не указывает число или тип параметра ( s) эта функция предназначена для приема.

Прототип:

int f(int, char);

... аналогично, но также указывает номер/тип параметра (ов), который предназначена для приема. Если он не принимает никаких параметров, вы используете что-то вроде int f(void), чтобы указать, что (поскольку оставить круглые скобки пустыми, это объявление). Определение функции нового стиля:

int f(int a, char b) { 
    // do stuff here...
}

... также выступает в качестве прототипа.

Без прототипа в области видимости компилятор применяет акции по умолчанию до аргументов перед вызовом функции. Это означает, что любой char или short он продвигается до int, а любой float продвигается до double. Поэтому, если вы объявляете (а не прототип) функцию, вы не хотите указывать какие-либо параметры char, short или float - вызов такой вещи будет/будет давать поведение undefined. С флагами по умолчанию компилятор может отклонить код, так как в принципе нет возможности использовать его правильно. Вы могли бы найти некоторый набор флагов компилятора, которые заставили бы его принять код, но это было бы совершенно бессмысленно, поскольку вы все равно не можете его использовать...

Ответ 2

Объявление int fuc(float); сообщает компилятору, что существует функция fuc, которая принимает float и возвращает int.

Определение int fuc(float f) { /*...*/ } сообщает компилятору, что на самом деле fuc, а также предоставляет декларацию.

Разница между объявлением и определением заключается в различии между тем, что существует синяя шляпа размера 6 и передается кому-то синюю шляпу размером 6: в заявлении говорится, что есть такая вещь, в определении говорится, что эта вещь прямо здесь это предмет, о котором идет речь.

Ответ 3

prototype = forward declaration, поэтому вы можете использовать его, прежде чем сообщать компилятору, что он делает. Однако он все еще имеет параметры.

Полезно во многих отношениях!