предупреждение о неявно объявленной функции существует потому, что большинство современных программ C не используют неявные функции.
Старый C89 разрешен для неявного объявления всего. Когда вы вызываете функцию, она становится неявным объявлением как int func()
. Это работает в этой ситуации, потому что вы неявно объявить функцию int cube()
с линией:
x = cube(x);
, а позже вы определяете функцию int cube(int)
. int cube()
и int cube(int)
имеют совместимые типы, поэтому это прекрасный вызов.
Проблема, с которой вы можете столкнуться, - это вызов несовместимой функции из неявно объявленной функции (это действительно почему предупреждение существует). int cube(float)
- это несовместимый тип функции, который определенно может существовать, и если вы назвали его с неявно объявленной функцией, вы, вероятно, могли бы ожидать некоторые довольно странные эффекты (прочитайте undefined). Как указано в mafso, строгий C99 больше не допускает неявно объявленных функций, поэтому многие компиляторы содержат предупреждение независимо.
Помните, что объявленная функция неявно объявлена BAD PRACTICE, но вы должны знать о существовании для таких сценариев.
Вот небольшая программа, демонстрирующая слабость неявно объявленных функций. Он использует некоторые из правил преобразования, которые вы ожидаете в программе c, которые внезапно исчезают с неявно объявленными функциями.
#include <stdio.h>
cube1(int x){return x*x*x;}
main(){float y = 9.; printf("%d\n%d\n", cube1(y), cube2(y));}
cube2(int x){return x*x*x;}
выход:
729
1
Эти функции идентичны в ассемблере
00000000004004dc <cube1>:
4004dc: 55 push %rbp
4004dd: 48 89 e5 mov %rsp,%rbp
4004e0: 89 7d fc mov %edi,-0x4(%rbp)
4004e3: 8b 45 fc mov -0x4(%rbp),%eax
4004e6: 0f af 45 fc imul -0x4(%rbp),%eax
4004ea: 0f af 45 fc imul -0x4(%rbp),%eax
4004ee: 5d pop %rbp
4004ef: c3 retq
0000000000400540 <cube2>:
400540: 55 push %rbp
400541: 48 89 e5 mov %rsp,%rbp
400544: 89 7d fc mov %edi,-0x4(%rbp)
400547: 8b 45 fc mov -0x4(%rbp),%eax
40054a: 0f af 45 fc imul -0x4(%rbp),%eax
40054e: 0f af 45 fc imul -0x4(%rbp),%eax
400552: 5d pop %rbp
400553: c3 retq
Но в callsite ожидаемый переход от поплавка до целого числа никогда не выполняется для неявного вызова.
Это c или C++? –
Речь идет не о порядке размещения функций в памяти (что в основном связано с компоновщиком). Речь идет о однопроходном компиляторе, который видит объявление функции перед вызовом этой функции. C++ в некоторой степени нарушает предположение «одного прохода», но только в некоторой степени. –
@chris no им не обязательно, он был объявлен, когда он был вызван (если это C) –