IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

为什么C语言需要函数声明

basic coder 2013-08-14 13:46:25 累计浏览 5,716 次
本机暂存

   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。

同分类推荐文章

  1. 科技爱好者周刊(第 401 期):如何赚到10亿美元 (2026-06-26 08:05:38)
  2. 如何做决策 - 从 Go 的一个 issue 说起 (2026-06-26 08:00:00)
  3. Seven Player:Windows上播放115网盘视频的增强工具 (2026-06-09 00:06:47)

查看更多 开发者 文章 →

建议继续学习

  1. Java程序员应该知道的10个eclipse调试技巧 (累计阅读 8,011)
  2. 从C语言的Hello World说起 (累计阅读 7,642)
  3. 使用gdb调试运行时的程序小技巧 (累计阅读 7,205)
  4. 程序员最怕的事 (累计阅读 6,923)
  5. 使用GDB调试多进程程序 (累计阅读 6,362)
  6. 一个程序员的血泪史 (累计阅读 6,319)
  7. php调试利器之phpdbg (累计阅读 5,673)
  8. C语言的那些个关键字们 (累计阅读 5,628)
  9. Nginx启动初始化过程(一) (累计阅读 5,552)
  10. PHP内核介绍及扩展开发指南―Extensions 的编写 (累计阅读 5,497)