关于隐式定义函数的警告,在clang中工作,在GCC 5.4中失败

时间:2016-10-10 13:22:09

标签: c gcc gcc-warning

我有一个基础C课程的参与者创造了一个谜。我们的任务是编写一个函数double square_to(double *),它只是将数字对齐,并返回结果。

剥离,代码如下所示:

main.c

#include "mymath.h"
#include <stdio.h>

int main() {
    double t = 5;
    double *p;
    double m;
    p = &t;
    m = square_to(p);
    printf("%f\n%f\n", t, m);
    return 0;
}

mymath.h

#ifndef MYMATH_H
#define MYMATH_H

double square_to(double *p);

#endif

mymath.c

#include "mymath.h"
#include <stdio.h>

double square_to(double *p) {
    *p = (*p) * (*p);
    return *p;
}

编译标志是:

-Wall -pedantic -o day5 main.c mymath.c

我认为没有任何问题。在他的Ubuntu和我的Fedora上,Clang和GCC也可以正常工作。该程序在每种情况下输出25.000两次。

奇怪的部分是使用原始文件的时候。 mymath.c中课程的其他部分还有其他一些功能。那些函数显然是编译的。在main.c中,他的GCC 5.4警告square_to的隐含声明。运行程序时,它会输出25.000和一些随机号,它看起来是一个整数。再次运行它会输出不同的号码。因此,这不是铸造问题,它是一种真正的未定义行为。

使用Clang编译相同的代码(仅在命令行中将gccclang交换,-Wall-Wpedantic处于活动状态),它运行正常,给出{{ 1}}在每种情况下。这是一个红旗,因为标准兼容代码应该与两个编译器编译得很好。在我的Fedora安装上,它适用于GCC 6.2.1。

完整代码位于此gist

我不知道为什么完整的代码会改变25.000函数的行为。整个计划有什么问题?

更新

在我离开教程之前,我让学生在gist中下载代码并编译它。他使用square_to这样做,并且编译时没有错误。运行它会给它gcc -Wall -pedantic main.c mymath.c

所以我的任何代码都没有问题。在他工作的目录中必须有一些非常奇怪的东西。我已经仔细检查了编辑器和终端中的路径,我也做了一个25.000 25.000,这是正确的。

现在没有办法回答这个问题,因为我没有任何东西可以重现这个问题。参与者还有其他各种类似的问题。看到这里的那些:

enter image description here

虽然函数中只有less main.c,但可以看到函数以某种方式调用double *。然后int指向一个声称存在冲突的声明,它是完全相同的原型。

我要关闭这个问题,因为如果没有访问参与者所具有的特定环境,就无法学到更多。他只是说明天他会在一个新目录中开始。如果它仍然存在,我将收集整个目录。

1 个答案:

答案 0 :(得分:1)

来自:Implicit function declarations sometimes work in C?

  

如果表达式位于括号中的参数列表之前   函数调用仅由标识符组成,如果没有声明   对于此标识符是可见的,隐式声明标识符   就像在包含函数调用的最里面的块中一样   宣言

extern int identifier();
     

出现。

因为main.c认为函数应该返回一个int,这就是你得到的(后来转换为赋值中的double)。

在运行Linux的Intel和AMD处理器上,整数在rax中返回,并且在浮点寄存器中返回双精度数。所以我的猜测是,在这种情况下,你看到的整数是函数返回时在rax寄存器中发生的任何事情。

但这只是猜测,未定义的行为未定义。

由于似乎存在一些混淆:如果您收到有关隐式声明的警告,这意味着GCC在使用之前没有看到任何有效的声明。要不然,或者你的编译器坏了。

在C <99中正确地声明返回函数是可选的,但强烈建议。