文章目录
GCC隐式声明
- main.c
#include<stdio.h>
char gNum[1024] = {1};
// GCC编译
int main()
{
int a = 1, b = 2;
add(a,b);
return 0;
}
- add.c
#include<stdio.h>
long long add(long long a1, long long a2)
{
long long ret = a1 + a2;
printf("ret1 = %lld, ", ret);
return ret;
}
- 编译命令
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc main.o add.o -o main
.\main
输出结果:ret1 = 3,
-
现象
PS C:\Users\482219\Desktop\test> gcc -c main.c -o main.o main.c: In function 'main': main.c:9:5: warning: implicit declaration of function 'add' [-Wimplicit-function-declaration] 9 | add(a,b); | ^~~ PS C:\Users\482219\Desktop\test> gcc -c add.c -o add.o PS C:\Users\482219\Desktop\test> gcc main.o add.o -o main PS C:\Users\482219\Desktop\test> .\main ret1 = 3, PS C:\Users\482219\Desktop\test> g++ -c main.c -o main.o main.c: In function 'int main()': main.c:9:5: error: 'add' was not declared in this scope 9 | add(a,b); | ^~~ PS C:\Users\482219\Desktop\test>
-
在GCC(C语言)下能编译通过但有警告的原因:
- C语言的隐式函数声明:在C语言中,如果调用一个未声明的函数,编译器会假设这个函数返回
int
类型,并接受任意数量和类型的参数(这是C语言的遗留特性)。这就是为什么你会看到"implicit declaration"的警告。 - 实际函数匹配:虽然你传入了两个
int
参数,而函数实际期望long long
参数,但由于C语言的宽松类型检查,编译器会生成代码将int
提升为long long
(因为这是C语言的标准整数提升规则)。 - 返回值处理:虽然隐式声明认为函数返回
int
,但实际返回long long
,这在C语言中通常也能工作,只是可能丢失精度或产生未定义行为。
- 在G++(C++)下编译失败的原因:
- C++更严格的类型检查:C++不允许隐式函数声明,必须在调用前声明函数。这是C++比C更严格的地方。
- 函数作用域规则:C++的错误信息"‘add’ was not declared in this scope"明确指出它找不到
add
的声明。 - 类型安全:即使你声明了函数,C++也不会像C那样自动将
int
参数转换为long long
参数,除非有显式的转换或函数重载。
- 如何修复:
要使代码在C和C++中都能正常工作,你应该:
-
添加函数声明:在
main.c
中添加add
函数的声明:c复制代码
long long add(long long a1, long long a2);
-
考虑参数类型:最好保持调用时的参数类型与函数声明一致,或者至少确保类型转换是安全的。
-
使用头文件(更好的做法):
-
创建
add.h
:
c复制代码
#ifndef ADD_H #define ADD_H long long add(long long a1, long long a2); #endif
-
在
main.c
和add.c
中都包含这个头文件
-
补充:
模块之间相互独立。假如add.c 里面的函数改了,main.c里面用extern,可以编译add()过,但根本不知道其他模块add()函数变化。最好在main.c和add.c里加头文件
全局变量 定义在函数外的变量叫全局变量,全局变量定义在bss段,bss段全是0。
未初始化的全局变量放bss段,已初始化的全局变量放data段
隐式声明函数,main.c 不知道add传什么类型的参数