当链接源中的函数定义与标题中的函数原型不同时,gcc不会发出警告

时间:2010-06-02 13:20:58

标签: c linux gcc prototype nan

我的代码的一部分出了问题,在一些迭代之后似乎将NaN读作结构的double的值。我想我发现了错误,但我仍然想知道为什么gcc(带有busybox的嵌入式Linux上的版本3.2.3)没有警告我。以下是代码的重要部分:

用于通过USB获取数据的函数的c文件及其标题:

// usb_control.h
typedef struct{
    double mean;
    short *values;
} DATA_POINTS;

typedef struct{
    int size;
    DATA_POINTS *channel1;
    //....7 more channels
} DATA_STRUCT;

DATA_STRUCT *create_data_struct(int N);  // N values per channel
int free_data_struct(DATA_STRUCT *data);

int aqcu_data(DATA_STRUCT *data, int N);

带有辅助函数的c和头文件(math,bitshift等等):

// helper.h
int mean(DATA_STRUCT *data);

// helper.c (this is where the error is obviously)
double mean(DATA_STRUCT *data)
{
    // sum in for loop
    data->channel1->mean = sum/data->N;
    // ...7 more channels
    // a printf here displayed the mean values corretly
}

主文件

// main.c
#include "helper.h"
#include "usb_control.h"

// Allocate space for data struct
DATA_STRUCT *data = create_data_struct(N);

// get data for different delays
for (delay = 0; delay < 500; delay += pw){
    acqu_data(data, N);
    mean(data);
    printf("%.2f",data->channel1->mean); // done for all 8 channels
    // printf of the mean values first is correct. Than after 5 iterations
    // it is always NaN for channel1. The other channels are displayed correctly;
}

没有段错误或任何其他错误行为,只是主文件中channel1的NaN。

找到错误后,这并不容易,当然是东方修复。 mean(){}的返回类型在定义中是错误的。而不是double mean(),它必须是原型定义的int mean()。当所有函数都放在一个文件中时,gcc警告我有一个函数mean()的重新定义。但是当我单独编译每个c文件然后链接它们之后,gcc似乎错过了。

所以我的问题就是。为什么我没有得到任何警告,即使没有gcc -Wall?或者是否还有另一个隐藏的错误,现在只是没有引起问题?

此致 基督教

2 个答案:

答案 0 :(得分:3)

当单独编译每个.c文件时,编译器知道的唯一信息就是您给出的函数原型。

因为每个文件都是单独编译的,所以main.c的编译器进程无法知道meanhelper.c的定义是错误的。

编译.c文件后,签名将被剥离,因此链接器无法知道mean是错误的。

一个简单的修复程序总是包含实现.h文件中的接口.c文件

// in helper.c:
#include "helper.h"
double mean(DATA_STRUCT *data);

然后helper.c的编译过程会注意到不一致的类型并警告你。

答案 1 :(得分:0)

平均值通常是实际值,所以双倍就可以了。在这里,您将mean定义为返回double,但原型显示为int mean(...)

gcc可以意识到存在重新定义这一事实的唯一方法是,如果重新定义是真实发生的......当你单独编译文件时可能会丢失平均原型......它没有显示在你的代码片段中至少:你应该把helper.h也包含在helper.c中。这样做,gcc -c helper.c必须给您一个警告。我有gcc 4.3.2,但我几乎可以肯定你的版本也必须如此。在主要内容中,您只需使用mean,因此此处gcc 信任 helper.h中的内容。当你链接时,没有关于参数大小和返回值的更多信息,并且会发生不好的事情(比如将int作为double读取)。

另一个细节:你说你得到一个结构的int的NaN ......好吧,在结构中有一个double,而int不能是NaN!