隐式声明与GCC内建函数

C语言隐式声明与GCC内建函数

什么是C语言的隐式声明

  在C语言中,函数在调用前不一定非要声明。如果没有声明,那么编译器会自动按照一种隐式声明的规则,为调用函数的C代码产生汇编代码。下面是一个例子:

#include <stdio.h>

int main() {
    double x = no_declare_func();
    return 0;
}
$ gcc -c implicitDeclare2.c 
$ gcc implicitDeclare2.o -o implicitDeclare2
implicitDeclare2.o: In function `main':
implicitDeclare2.c:(.text+0xe): undefined reference to `no_declare_func'
collect2: error: ld returned 1 exit status

  可以看到上面的代码没有定义no_declare_func,但是gcc在编译的时候并不会报错,因为C语言规定,对于没有声明的函数,自动使用隐式声明,也就变成如下代码(函数的隐式声明默认为int型):

#include <stdio.h>

int no_declare_func();
int main() {
    double x = no_declare_func();
    return 0;
}

  在链接的时候会报错,因为链接过程中没有找到函数no_declare_func的定义。
  目前C++是没有隐式声明这一说,遇到这种没有函数声明的情况,会直接报error。

GCC内建函数

  内建函数(built-in),即一个系统或者工具提供的默认就能用的函数,我的理解是默认情况下,gcc在链接的时候如果没有找到定义,就会自动去链接库中对应名称的函数,gcc的内建函数大多是为了对代码进行优化。
  gcc内建函数相关的选项如下:

  • -fbuiltin:
    gcc编译默认选项,默认通过名字来识别内建函数

  • -fno-builtin:
    禁用GCC编译器内建函数。如果在gcc编译时用了-fno-builtin选项,则除非利用前缀__builtin_进行引用,否则不识别所有内建函数。例如,为了获得内建strcpy函数,应该调用__builtin_strcpy()而不是名为 strcpy() 的函数。

  • -fno-builtin-xxx:
    gcc编译时想特定的不使用某些函数的内建函数,例如,想使用除sqrt()之外的所有内建函数,则可以添加此选项-fno-builtin-sqrt

隐式声明带来的灾难

  不要用隐式声明!!!不要用隐式声明!!!不要用隐式声明!!!

  1. 首先,隐式声明是默认int型,如果没有对应同名的内建函数,编译不报错,链接报错,这种情况上面已经介绍
  2. 有同名的内建函数,且类型相同,gcc编译链接没问题
  3. 有同名的内建函数,类型不同,链接报warning“隐式声明与内建函数不兼容”,但是以内建函数的函数原型为准。gcc编译器在编译时能够自动在常用库头文件(内建函数)中查找与隐式声明同名的函数,如果发现两者并不相同,则会按照内建函数的声明原型去生成调用代码。

case 2:

#include <stdio.h>

int main(){
    int x = abs(-1,2,3,4,5);
    printf("%d \n", x);
    return 0;
}

  其中,abs的隐式声明函数原型为:

int abs(int);

  abs()内建函数原型为:

int abs(int);

  gcc编译链接均没有报错,执行结果如下:

$ gcc -c implicitDeclare.c
$ gcc implicitDeclare.o -o implicitDeclare
$ ./implicitDeclare 
1 

  可见,gcc的内建函数机制并不关心函数的参数,只是关心函数的返回值。虽然这个例子的运行结果都是正确的,但是这种正确是“碰巧”的,因为额外的函数参数并没有影响到结果。这种偶然正确是程序中要避免的。

case 3:

#include <stdio.h>

int main(){
    double x = sqrt(1);
    printf("%lf \n", x);
    return 0;
}

  其中,sqrt()的隐式声明函数原型为:

int sqrt(int);

  sqrt()的内建函数原型为:

double sqrt(double);

编译报警告,链接按照内建函数原型链接:

$ gcc -c implicitDeclare.c
implicitDeclare.c: In function ‘main’:
implicitDeclare.c:4:16: warning: incompatible implicit declaration of built-in function ‘sqrt’ [enabled by default]
     double x = sqrt(1);
                ^
$ gcc implicitDeclare.o -o implicitDeclare

但是仍然可以执行,结果如下:

$ ./implicitDeclare 
1.000000 
<think>我们正在讨论C语言中的声明问题。用户询问如何使用gcc声明视为错误(error)的方法。 在C语言中,声明是指函数在使用前没有进行声明,这在C99标准之后被视为错误。gcc编译器提供了一些选项来检测并处理这种情况。 方法: 1. 使用 `-Werror=implicit-function-declaration` 选项:这个选项会将函数声明的警告(warning)升级为错误(error)。 2. 使用 `-Werror` 选项:这个选项会将所有警告都视为错误。由于函数声明gcc中是一个警告(warning: implicit declaration of function),所以使用这个选项也会将其变为错误。 注意:在C99及以后的标准中,函数声明已经被禁止,因此使用`-std=c99`或`-std=c11`等选项时,如果出现声明gcc会给出警告(在没有使用`-Werror`的情况下)或错误(在使用`-Werror`或`-Werror=implicit-function-declaration`的情况下)。 因此,推荐的编译选项是: gcc -std=c99 -Werror=implicit-function-declaration ... 或者 gcc -std=c99 -Werror ... 这样,当代码中出现函数声明时,编译会失败并报错。 另外,为了完全避免声明,应该始终在使用函数之前声明或定义函数。在头文件中声明函数,并在源文件中包含相应的头文件,是良好的编程实践。 现在,按照要求,我们需要在回答后提出3-5个相关问题,并以“§§相关问题§§”开头,然后列出问题。</think>在C语言中,使用GCC编译器时,可以通过以下方法将函数声明视为编译错误: 1. **使用特定警告选项**: `-Werror=implicit-function-declaration` 选项将声明警告转换为错误: ```bash gcc -Werror=implicit-function-declaration your_file.c ``` 2. **使用严格模**: 结合C99或更高标准(声明在C99后非法)`-pedantic-errors`: ```bash gcc -std=c99 -pedantic-errors your_file.c ``` 3. **全局警告转错误**(谨慎使用): `-Werror` 将所有警告转为错误(包括声明): ```bash gcc -Werror your_file.c ``` **效果说明**: - 上述方法会在遇到声明时直接报错终止编译,例如: ``` error: implicit declaration of function 'func' [-Werror=implicit-function-declaration] ``` - 推荐使用`-Werror=implicit-function-declaration`进行精准控制,避免影响其他警告。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值