implicit-function-declaration

一般情况下如果我们想使用其他文件的函数时,常规操作是将该函数在头文件中声明,然后在需要使用的文件里引用这个头文件 但若是没声明呢?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
11.c
#include <stdio.h>
extern char* b;
int main() {
    printf("aaa--d:%x----%s--p\n", aaa(),b,b);

    char*p = aaa();

    printf("p = %p\n", p);
    if(p)
        printf("---\n");
    printf("value = %s\n"p);// 崩溃!
    return 0;
}

2.c
char *b="aaa";
char* aaa(){ return b;}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
gcc 11.c 2.c -o test
11.c: In function ‘main'
11.c:4:37: warning:: implicit declaration of function ‘aaa'[-Wimplicit-function-declaration]
 4| printf("aaa--d:%x----%s--%p\n",aaa(),b,b);
 | ^~~
11.c:5:15: warning:: initialization of ‘char *’ fromn‘int' makes pointer from integer without a cast [-Wint-conversion]
 5| char *p = aaa();
 | ^~~
./test
aaa--d:4b1c032----aaaa--0x560604b1c032
p=0x4b1c032
---
Segmentation fault (core dumped)

这里并没有引用这个头文件,为什么依然可以使用呢?

这就引出了一个概念:隐式声明

简单来讲就是当前文件使用没有声明的函数时,编译器会自动声明一个,但返回值是int类型

那为什么会出现段错误呢? 上面编译运行的环境是64bit的:

char* aaa() 返回的是一个指针8B(64bit) 但是在编译时 已经确定了是返回值类型(由于是隐式声名,编译器默认是int) 是int 4B(32bit) ,所以就会把指针的低32bit 取出来 赋给char* *p 指针p 的值就是一个截断的值, 这个指针就变成了一个非法的了,如果取访问其指向的内存,就会出现 段错误.

如果是32bit 环境呢

int 是4B 指针也是4B ,指针不会被截断,还是原来的值,不会出现非法访问.

如何避免呢: 在Makefile 里加上 -Wall -Werror ,编译时会检测出这种错误

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计