C语言使用函数前为什么要声明是个老问题了,还是没忍住想简单记一下,事情原于同事写的一段测试代码。
前两天同事拿来一段C代码让我帮忙看下,main()函数里面调用了一个另一个函数,该函数返回double值,在函数内部return之前printf打印出来的返回值和在函数调用后的返回值差别非常大,我刚开始迷迷呼呼还奇怪了半天,后来把编好的binary反汇编看了一眼就知道怎么回事了,假设函数名是func,在汇编代码的main代码块里面发现这样一句话:
callq 400550 <func> cvtsi2sd %eax,%xmm0
我次凹,这是怎么回事,x86_64汇编不是浮点型返回值不是会直接放在xmm0寄存器里面吗,为什么还会有一条奇怪的cvtsi2sd这样的指令,于是就意识到main代码块和func函数没有在一个c文件里面,而在编译的时候两个源文件是单独进去编译的,在编译完成后才会由链接器把目标文件链接起来,这也就是为什么声明是必须的,如果函数在其它的源文件中定义,没有在引用的源文件中声明,那编译器只知道要调这样一个函数,既不知道该给它传什么参数(传任务参数编译器都会认为是合法的),也不知道该返回什么值,x86_64上编译器把整形或地址返回值放在eax/rax中,浮点型放入xmm0中,单从返回值上来看,编译器默认是把这个陌生函数的返回值定为整形,由于在外层期望的是个浮点型,编译器在调用完func后就把整形的返回值再转换成浮点型放入xmm0中,也就导致了上述的问题。
返回值是一方面,函数参数会带来更难调试的问题,x86_64在参数较少时使用寄存器传参,ia32使用栈传参,这时候如果外部函数未声明,那你传错误的参数也是能编译通过的,但最后的结果就是各种诡异了,往往会带来一些复杂难调的问题,但其实对于gcc来说,打开-Wimplicit-function-declaration选项的话这些未声明的问题都是会有warning提示的:
warning: implicit declaration of function ‘func’
所以好的编程习惯是打开-Wall,消除所有的warning。
转载请注明:爱开源 » 为什么C语言需要函数声明