c - 有关 C 函数原型(prototype)和编译的问题

标签 c gcc compiler-construction

使用以下代码:

int main(){
    printf("%f\n",multiply(2));
    return 0;
}

float multiply(float n){
    return n * 2;
}

当我尝试编译时,我收到一个警告:“'%f'需要'double',但参数具有类型'int'”和两个错误:“'multiply'的类型冲突”、“'的先前隐式声明”乘法'就在这里。”

问题1:我猜测这是因为,鉴于编译器第一次遇到函数“乘法”时并不了解它,他会发明一个原型(prototype),并且总是发明原型(prototype)假设'int'既被返回又被作为参数。因此,发明的原型(prototype)将是“int multiply(int)”,因此会出现错误。这是正确的吗?

现在,之前的代码甚至无法编译。但是,如果我将代码分解为两个文件,如下所示:

#file1.c
 int main(){
    printf("%f\n",multiply(2));
    return 0;
 }

#file2.c
float multiply(float n){
    return n * 2;
}

并执行“gcc file1.c file2.c -o file”,它仍然会给出一个警告(printf 期望 double 但正在获取 int),但错误将不再显示并且它将编译。

问题 2:为什么我将代码分成 2 个文件来编译?

问题 3:一旦我运行上面的程序(版本分为 2 个文件),结果是 0.0000 打印在屏幕上。怎么会?我猜编译器又发明了一个与函数不匹配的原型(prototype),但为什么打印出 0 呢?如果我将 printf("%f") 更改为 printf("%d") 它会打印 1。同样,对幕后发生的事情有任何解释吗?

提前非常感谢。

最佳答案

So the invented prototype would be "int multiply(int)", and hence the errors. Is this correct?

绝对是的。这样做是为了向后兼容 ANSI C 之前的版本,因为 ANSI C 缺乏函数原型(prototype),并且没有类型声明的所有内容都是隐式 int 的。编译器编译您的 main,创建 intmultiply(int) 的隐式定义,但是当它找到真正的定义时,它会发现谎言,并告诉您它。

How come when I break the code into 2 files it compiles?

编译器永远不会发现原型(prototype)的谎言,因为它一次编译一个文件:它假设 multiply 接受一个 int,并返回一个 int 在您的 main 中,并且在 multiply.c 中没有发现任何矛盾。不过,运行该程序会产生未定义的行为。

Once I run the program above (the version split into 2 files) the result is that 0.0000 is printed on the screen.

这是上述未定义行为的结果。程序将编译并链接,但由于编译器认为 multiply 采用 int,因此它永远不会将 2 转换为 2.0F multiply 永远不会找到答案。同样,通过在 multiply 函数中将 int 加倍重新解释float 计算出的错误值将被视为又是一个int

关于c - 有关 C 函数原型(prototype)和编译的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33702652/

相关文章:

c - C 队列实现中的段错误

c - 在文件读取中添加 null 的位置

c++ - 海湾合作委员会错误 : expected primary-expression before ')' token with MSVC C++ code

C++编译错误?

gcc - 有没有办法单独输出单个函数的程序集?

c - 如何管理 C 函数中的任意参数

c - UEFI hello world编译错误

linux - 创建在 mac 10.6 上运行的 linux 交叉编译器

scala - 如何在 Scala 编译器插件中以文本形式生成新的源代码?

c++ - 编译netbean时出错