代码之家  ›  专栏  ›  技术社区  ›  taurus05

函数返回类型不是int时的未定义行为

  •  0
  • taurus05  · 技术社区  · 3 年前

    考虑 snippet 1 :

    #include <stdio.h>
    
    int main() {
        float val;
        val = fun(2, 4);
        printf("%f", val);
        
        return 0;
    }
    float fun(int x, int y){
        return x+y;
    }
    

    密码 snippet 2 :

    #include <stdio.h>
    
    int main() {
        int val;
        val = fun(2, 4);
        printf("%d", val);
        
        return 0;
    }
    int fun(int x, int y){
        return x+y;
    }
    

    在代码段1的情况下,它会给我错误,如下所示:

    gcc /tmp/1cUl25Ux4O.c -lm
    /tmp/1cUl25Ux4O.c: In function 'main':
    /tmp/1cUl25Ux4O.c:6:11: warning: implicit declaration of function 'fun' [-Wimplicit-function-declaration]
        6 |     val = fun(2, 4);
          |           ^~~
    /tmp/1cUl25Ux4O.c: At top level:
    /tmp/1cUl25Ux4O.c:11:7: error: conflicting types for 'fun'
       11 | float fun(int x, int y){
          |       ^~~
    /tmp/1cUl25Ux4O.c:6:11: note: previous implicit declaration of 'fun' was here
        6 |     val = fun(2, 4);
          |           ^~~
    

    但在第二个片段的情况下,我得到了正确的输出。(即 6 )。
    在这两种情况下,我都省略了函数声明,只出现了定义部分,在main()之后也是如此。 但是,如果 摘录1 ,如果我在main()之前更改顺序并定义fun(int,int),我就会得到所需的输出。(即 6.0000 )
    我想不通。

    为什么会发生这种情况?
    这是因为函数被推入堆栈的顺序吗?
    如果这就是原因,那么为什么代码段2中的代码可以工作呢?
    请给我提供参考资料/解释。谢谢

    更新:
    在代码段1的错误日志中,它指出 conflicting types for fun 。但是代码中只有一个有趣的(int,int)。什么在制造冲突?

    0 回复  |  直到 3 年前
        1
  •  4
  •   Jabberwocky    3 年前

    第一个片段:

    int main() {
        float val;
        val = fun(2, 4);
        printf("%f", val);
        
        return 0;
    }
    float fun(int x, int y){
        return x+y;
    }
    

    当你写作 val = fun(2, 4); 在里面 main 编译器尚未遇到 float fun(int x, int y) 因此,它假设 fun 声明如下: int fun(); (函数返回 int 并且取任意数量的任意类型的参数。

    然后编译器遇到 float fun(int x,int y) ,但如前一段所述,编译器现在假设 享乐 返回 int ,因此产生了冲突。

    如果你把 float fun(int x,int y) 之前 主要的 ,编译器遇到 float fun(int x,int y) 现在知道了 享乐 返回 float 正好需要两个 int 论点。

    隐式声明已经成为过去,现在不应该再使用了。

    顺便说一句:

    没有 未定义行为 参与其中。 未定义的行为 是完全不同的东西。

    我建议您阅读以下内容: Undefined, unspecified and implementation-defined behavior

        2
  •  2
  •   Lundin    3 年前

    但在第二个片段的情况下,我得到了正确的输出。

    不,它也不编译。为了避免编译器已经发现错误的代码疑难解答的麻烦,请确保使用一致的C编译器,请参阅 What compiler options are recommended for beginners learning C?

    当使用正确配置的兼容C编译器时,我们会得到以下错误:

    错误:函数'fun'的隐式声明

    某些编译器决定在未设置为严格遵守模式时生成可执行文件的原因是历史原因。32年前(古代!)的编译器有一个叫做“隐式函数声明”和“隐式int”的特性。这意味着,当编译器遇到对尚未声明/定义的函数的函数调用时,它猜测该函数的返回类型为 int 。因为为什么不呢?在某些情况下,它可能是正确的类型!

    如果不是这样,我们会得到未定义的行为,任何事情都可能发生。例如函数返回 float 但是调用方正在处理它的原始二进制表示 浮动 作为 int 。或者程序崩溃。

    在23年前发布的C99版本中,这个语言设计缺陷已从C中删除。

    您可能没有理由使用古老的编译器模式,所以只需使用上面链接中给出的选项进行编译即可。