1

我的部分代码有问题,经过一些迭代后,它似乎将 NaN 读取为double结构的 a 值。我想我找到了错误,但我仍然想知道为什么 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 和头文件:

// 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?或者是否还有另一个隐藏的错误现在不会引起问题?

问候,基督徒

4

2 回答 2

3

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

因为每个文件都是单独编译的,所以编译过程不可能main.c知道meanin的定义helper.c是错误的。

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

一个简单的解决方法是始终.h在实现文件中包含接口.c文件

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

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

于 2010-06-02T13:28:00.497 回答
0

平均值通常是一个实数值,所以双倍是可以的。在这里,您定义mean为返回 double,但原型说int mean(...).

gcc 可以知道存在重新定义这一事实的唯一方法是,如果重新定义是真实发生的……当您单独编译文件时,可能缺少平均原型……它至少没有显示在您的代码片段中:您应该将 helper.h 也包含到 helper.c 中。这样做,gcc -c helper.c必须给你一个警告。我有 gcc 4.3.2,但我几乎可以肯定你拥有的版本也必须如此。总的来说,你只是使用mean,所以这里 gcc信任helper.h. 链接时,没有关于参数大小和返回值的更多信息,并且会发生不好的事情(例如将 int 读取为双精度)。

另一个细节:你说你得到 NaN 作为结构的 int ......好吧,在结构中有一个双精度数,而 int 不能是 NaN!

于 2010-06-02T13:40:37.663 回答