做标书的视频网站,常用搜索引擎有哪些,阿里云轻云服务器可以放多个网站啊怎么做,小语种建站「1、什么是C语言的隐式函数声明」在C语言中#xff0c;函数在调用前不一定非要声明。如果没有声明#xff0c;那么编译器会自动按照一种隐式声明的规则#xff0c;为调用函数的C代码产生汇编代码。下面是一个例子#xff1a;int main(int argc, char** argv)
{double x a… 「1、什么是C语言的隐式函数声明」在C语言中函数在调用前不一定非要声明。如果没有声明那么编译器会自动按照一种隐式声明的规则为调用函数的C代码产生汇编代码。下面是一个例子int main(int argc, char** argv)
{double x any_name_function();return 0;
}单纯的编译上述源代码并没有任何报错只是在链接阶段因为找不到名为any_name_function的函数体而报错。[smstongcentos192 test]$ gcc -c main.c
[smstongcentos192 test]$ gcc main.o
main.o: In function main:
main.c:(.text 0x15): undefined reference to any_name_function
collect2: ld 返回 1之所以编译不会报错是因为C语言规定对于没有声明的函数自动使用隐式声明。相当于变成了如下代码int any_name_function();
int main(int argc, char** argv)
{double x any_name_function();return 0;
}「2、带来的问题」「2.1 隐式声明函数名称恰好在链接库中存在但返回非int类型」前面给出的例子并不会造成太大影响因为在链接阶段很容易发现存在的问题。然而下面这个例子则会造成莫名的运行时错误。#include
int main(int argc, char** argv)
{double x sqrt(1);printf(%lf, x);return 0;
}gcc编译链接[smstongcentos192 test]$ gcc -c main.c
main.c: 在函数‘main’中:
main.c:6: 警告隐式声明与内建函数‘sqrt’不兼容
[smstongcentos192 test]$ gcc main.o运行结果1.000000编译时会给出警告提示隐式声明与内建函数’sqrt’不兼容。gcc编译器在编译时能够自动在常用库头文件内建函数中查找与隐式声明同名的函数如果发现两者并不相同则会按照内建函数的声明原型去生成调用代码。这往往也是程序员预期的想法。上面的例子中隐式声明的函数原型为int sqrt(int);而对应的同名内建函数原型为double sqrt(double);最终编译器按照内建函数原型进行了编译达到了预期效果。然而gcc编译器的这种行为并不是C语言的规范并不是所有的编译器实现都有这样的功能。同样的源码在VC 2015下编译运行的结果却是VC 编译warning C4013: “sqrt”未定义假设外部返回 int运行结果2884223.000000显然VC 编译器没有没有所谓的“内建函数”只是简单的按照隐式声明的原型生成调用sqrt函数的代码。由于返回类型和参数类型的不同导致错误的函数调用方式产生莫名奇妙的运行时错误。对着这种情况由于返回类型的不同两种编译器都可以给出警告信息至少能引起程序员的注意。而下面这种情况则更加隐蔽。「2.2 隐式声明函数名称恰好在链接库中存在且返回int类型」测试代码如下#include int main(int argc, char** argv)
{int x abs(-1);printf(%d, x);return 0;
}此时由于隐式声明的函数原型与gcc的内建函数原型完全相同所以gcc不会给出任何警告结果也是正确的。而VC 则仍然会给出警告warning C4013: “abs”未定义假设外部返回 int。无论如何隐式声明的函数原型与库函数完全相同所以链接运行都是没有问题的。下面稍微改动一下代码#include int main(int argc, char** argv)
{int x abs(-1,2,3,4);printf(%d, x);return 0;
}gcc下编译链接没有任何报错。gcc编译链接[smstongcentos192 test]$ gcc -c main.c
[smstongcentos192 test]$ gcc main.o可见gcc的内建函数机制并不关心函数的参数只是关心函数的返回值。vc 编译链接warning C4013: “abs”未定义假设外部返回 int虽然这个例子的运行结果都是正确的但是这种正确是“碰巧”的因为额外的函数参数并没有影响到结果。这种偶然正确是程序中要避免的。「3、编程中注意事项」C语言的隐式函数声明给程序员带来了各种困惑给程序的稳定性带来了非常坏的影响。不知道当初C语言设计者是如何考虑这个问题的为了避免这种影响强烈建议程序员重视编译器给出的关于隐式声明的警告及时通过包含必要的头文件来消除这种警告。对于gcc来说前面给出的那个abs(-1,2,3,4)的特殊例子编译器根本不会产生任何警告只能靠程序员熟悉自己调用的每一个库函数了。为了避免这种问题在C语言的C99版本中无论如何都会给出警告。如gcc使用C99编译上述代码。gcc -stdc99编译[smstongcentos192 test]$ gcc -c main.c -stdc99
main.c: 在函数‘main’中:
main.c:5: 警告隐式声明函数‘abs’而C 则更严格直接抛弃了隐式函数声明对于未声明函数的调用将直接无法通过编译。g 编译[smstongcentos192 test]$ g main.c
main.c: In function ‘int main(int, char**)’:
main.c:5: 错误‘abs’在此作用域中尚未声明vc 编译作为C )error C3861: “abs”: 找不到标识符在函数强类型这一点上C 确实比C更严格更严谨。来源https://blog.csdn.net/smstong/