Почему пустое объявление работает для определений с аргументами int, но не для аргументов с плавающей точкой? - PullRequest
12 голосов
/ 30 марта 2011

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

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

int fuc();

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

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

int fuc();

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

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

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

Ответы [ 3 ]

23 голосов
/ 30 марта 2011

Декларация:

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 - вызов такой вещи будет / будет давать неопределенное поведение , С флагами по умолчанию компилятор вполне может отклонить код, поскольку в принципе нет способа его правильно использовать. Вы могли бы найти некоторый набор флагов компилятора, который заставил бы его принять код, но это было бы довольно бессмысленно, поскольку вы все равно не можете его использовать ...

0 голосов
/ 30 марта 2011

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

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

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

0 голосов
/ 30 марта 2011

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

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

...