我在项目中遇到了一些奇怪的gcc警告。让我们在3个文件中看看这个简单的例子:
struct.h
typedef struct {
int a;
long b;
char *c;
} myStruct;
函数c
#include <stdio.h>
#include <stdlib.h>
#include "struct.h"
myStruct* func() {
myStruct* new = (myStruct*) malloc(sizeof(myStruct));
new->a = 42;
new->b = 84;
new->c = "lol_okn";
return new;
}
void prn(myStruct* x) {
printf("%dn", x->a);
}
main.c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "struct.h"
int main() {
myStruct* ms = func();
prn(ms);
return 0;
}
所以我得到以下警告:
main.c: In function ‘main’:
main.c:8:24: warning: initialization makes pointer from integer without a cast
myStruct* ms = func();
此外,当我用-Wall -Wextra
构建它时,我得到了更多:
main.c: In function ‘main’:
main.c:8:9: warning: implicit declaration of function ‘func’ [-Wimplicit-function-declaration]
myStruct* ms = func();
^
main.c:8:24: warning: initialization makes pointer from integer without a cast
myStruct* ms = func();
^
main.c:9:2: warning: implicit declaration of function ‘prn’ [-Wimplicit-function-declaration]
prn(ms);
这一切意味着什么?如果使用-fsanitize=undefined -fsanitize=address
构建,它也会崩溃,这很奇怪。为什么?
缺少原型。
在struct.h
中包含func()
的原型。
myStruct* func(void);
当func()
没有可见的原型时,编译器假设(C99之前)它返回一个int
。但是func()
实际上返回一个myStruct*
。
请注意,此隐式int规则已被从C99中删除。因此,从技术上讲,C99和C11中的代码格式不正确。
提高警告级别会有所帮助。gcc提供了一个捕捉这个的选项:
-Wimplicit-function-declaration
main.c:8:9: warning: implicit declaration of function ‘func’ [-Wimplicit-function-declaration]
这意味着main.c不知道函数func
是什么样子的。这是因为它是在func.c中定义的,但main.c看不到func.c.中有什么。
您需要做的是将func()
的声明放在struct.h中,如下所示:
myStruct* func( void );
一旦你有了它,那么main.c就知道函数func
是什么了
此外,之所以得到"initialization make pointer from integer without a cast",是因为在没有看到函数声明的情况下,编译器假设它返回int
。