C语言 百分网手机站

C 语言声明与定义不一致导致的问题

时间:2020-09-26 20:46:29 C语言 我要投稿

C 语言声明与定义不一致导致的问题

  我们在写代码的时候,往往只注意函数的实现,对函数的声明重视不足。下面是小编为大家带来的C 语言声明与定义不一致导致的问题,欢迎阅读。

  C 语言声明与定义不一致导致的问题

  最近项目代码需要从mips平台移植到x86平台,这是公司产品第一次采用x86平台。之前项目很紧,所以很多代码都没有考虑移植性问题,因此移植的时候遇到了不少问题。前几天才解决了位序(也叫比特序,与字节序不同)问题,今天又遇到了一个比较隐蔽的C语言问题,在这里记录一下,告诫自己,也告诫各位同行,避免犯这样的错误。至于位序问题,以后应该会再另写一篇文章来说明。

  原本在mips平台上运行良好的代码,移植到了x86平台,结果却不对了,我们仔细分析了代码,没发现什么可疑的地方,而且我之前为了优化那段代码,单独把那段代码抽出来测试过。我抽出来的代码在两个平台里得出的都是一样的结果。我对比了代码,实现的地方没有任何改动,照理说不应该出现这种情况的'。不过根据打印出来的值,我注意到了一种情况,在x86平台里的结果值只有16位,但在mips平台里的结果值有32位,并且低16位的值与x86平台下的值一样。最后,我查看了声明该函数的头文件,才发现头文件里函数的声明与C文件里的实现返回值不一致!

  问题可以简化成下面的代码:

  //crc.c

  //注意,此处没有包含crc.h这个头文件!

  unsigned int get_crc(void)

  {

  return 0x12345678;

  }

  //crc.h

  unsigned short get_crc(void);

  //main.c

  #include

  #include "crc.h"

  int main(int argc, char *argv[])

  {

  unsigned int crc = get_crc();

  printf("crc:%x ", crc);

  return 0;

  }

  编译执行: gcc -Wall -o test main.c crc.c //好吧,-Wall也没办法报错

  在x86平台下输出:5678

  我又分别在mips平台和powerpc平台下编译执行了这段代码,同样没警告或者报错。在mips平台下输出:12345678,在powerpc平台下输出:12345678

  在简化的代码里,大家很容易就能看出是get_crc这个函数的声明和定义(实现)不一致导致的问题,但在庞大的项目文件里,可能就没那么容易看出问题所在了。

  我们在写代码的时候,往往只注意函数的实现,对函数的声明重视不足。在Linux平台下,我们喜欢用cscope+ctags+vim来写代码,修改或者浏览代码的时候也喜欢跳到函数定义处,变量声明处,却很少关注函数声明,导致修改代码之后声明和定义不一致的情形。

  这并不只是程序新手才会出现的问题,工作几年的程序员也可能会犯这样的错误,出现问题的这段代码,就是出自一个已经工作了四年的同事之手。

  也正是在这个时候,我才发现,我们之前的代码是有问题的,只是所谓的“得到了正确的结果”。

  我起先认为对于这种情况,是个编译器未定义形为,不同gcc版本对这种情况的处理可能不一样,但我进行了一些测试,发现情况比我想象中的复杂。在powerpc平台,gcc版本是3.3.x,mips平台,gcc版本是4.3.x,在x86平台,有两个版本的编译器,分别为4.1.x(centos),4,6.x(ubuntu)执行情况是mips平台和powerpc平台一样,都是12345678,x86平台下均为5678。mips和powerpc都是大端,x86是小端,至令我没办法判断真正的问题在哪,是编译器版本原因还是与大小端有那么点关系。还望知道的朋友不吝赐教。

  此外,我还测试了对于变量的情况,发现对于变量的处理,各个gcc版本不同平台都是一致的,当然,由于大小端的关系,输出结果会不同。大家有兴趣可以试一下。

  说了那么多,只是想说明这个隐蔽的错误大家一不小心就很容易犯,而且后果也比较严重,得找到方法避免。解决办法很简单,那就是通过把函数声明(原型)放在头文件中,而函数定义则放在另一个包含了该头文件的源文件中。这样编译器就能发现不一致的情况从而报错提醒我们。这个问题在《C专家编程》8.5节有论述。


【C 语言声明与定义不一致导致的问题】相关文章:

C语言变量的定义与使用10-05

C语言变量定义02-27

C语言宏定义10-06

C语言声明的语法10-07

简单讲解C语言中宏的定义与使用11-19

C语言自定义函数10-04

关于C语言宏定义的技巧11-23

C语言程序中函数的定义10-03

Java中定义与声明的区别10-05