GCC隐式声明和头文件

文章目录

GCC隐式声明

  1. main.c
#include<stdio.h>

char gNum[1024] = {1};

// GCC编译
int main()
{
    int a = 1, b = 2;
    add(a,b);
    return 0;
}
  1. 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;
}
  1. 编译命令
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc main.o add.o -o main
.\main

输出结果:ret1 = 3,

  1. 现象

    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>
    
  2. 在GCC(C语言)下能编译通过但有警告的原因:

  • C语言的隐式函数声明:在C语言中,如果调用一个未声明的函数,编译器会假设这个函数返回int类型,并接受任意数量和类型的参数(这是C语言的遗留特性)。这就是为什么你会看到"implicit declaration"的警告。
  • 实际函数匹配:虽然你传入了两个int参数,而函数实际期望long long参数,但由于C语言的宽松类型检查,编译器会生成代码将int提升为long long(因为这是C语言的标准整数提升规则)。
  • 返回值处理:虽然隐式声明认为函数返回int,但实际返回long long,这在C语言中通常也能工作,只是可能丢失精度或产生未定义行为。
  1. 在G++(C++)下编译失败的原因:
  • C++更严格的类型检查:C++不允许隐式函数声明,必须在调用前声明函数。这是C++比C更严格的地方。
  • 函数作用域规则:C++的错误信息"‘add’ was not declared in this scope"明确指出它找不到add的声明。
  • 类型安全:即使你声明了函数,C++也不会像C那样自动将int参数转换为long long参数,除非有显式的转换或函数重载。
  1. 如何修复:

要使代码在C和C++中都能正常工作,你应该:

  1. 添加函数声明:在main.c中添加add函数的声明:

    c复制代码

    long long add(long long a1, long long a2);
    
  2. 考虑参数类型:最好保持调用时的参数类型与函数声明一致,或者至少确保类型转换是安全的。

  3. 使用头文件(更好的做法):

    • 创建

      add.h
      

      c复制代码

      #ifndef ADD_H
      #define ADD_H
      long long add(long long a1, long long a2);
      #endif
      
    • main.cadd.c中都包含这个头文件

补充:
模块之间相互独立。假如add.c 里面的函数改了,main.c里面用extern,可以编译add()过,但根本不知道其他模块add()函数变化。最好在main.c和add.c里加头文件

全局变量 定义在函数外的变量叫全局变量,全局变量定义在bss段,bss段全是0。
未初始化的全局变量放bss段,已初始化的全局变量放data段

隐式声明函数,main.c 不知道add传什么类型的参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值