码迷,mamicode.com
首页 > 编程语言 > 详细

zerglurker的C语言教程010——运算符详解(三)

时间:2015-06-17 09:38:34      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:c++   c语言   语言   编程   教程   

同上节课,请参考运算符总览

本节主要讲讲sizeof

也许有的资料提到过C++的typeid,但是这个根本不是运算符,而是一个类,有文件定义的

所谓运算符必须是无需头文件即可使用的符号。如果要使用一个运算符,还需要头文件,那么这个运算符就不是基本的运算符,是开发人员重载或者自己写的。

从这个角度看typeid就不是运算符,而是微软自定义的。

运算符的另一个特点是,对常量进行操作,编译阶段就会进行处理。

比如 int a = sizeof(int) ;

编译器会在编译的时候直接将4用来初始化a。所以你不能指望a的值是动态的:在16位系统它是2,32位系统它是4 。

相反的,它是固定的,具体的取值决定于编译器:16位的编译器会给2,32位的编译器会给4 。

请注意:64位的编译器不会给8,仍然是给4——因为大部分程序员认为整数就是4字节,为了遵从这个标准,后面的编译器都认为int就是4字节,不再扩展int的长度了

我们在使用sizeof的时候会跟一个括号,但是这个括号不是必须的,只是用来规范优先级!

上面的示例也可以写成这样:

int a = sizeof int  ;

结果仍然不变。但是复杂一点的情况就比较麻烦了:

int b = sizeof a * 4 ;

尽管我们知道sizeof的优先级比乘法高,但是这样写让代码无法一目了然,容易产生歧义。

int b = sizeof(a) * 4 ;

这样写就没有任何歧义了,看上去也一目了然。

当然这里会因为编译器而产生一个陷阱,其实b的值不一定是16,也可能是8 。

所以很多时候,这个运算符被用来进行内存操作:

int a[16];
memset(a,0,sizeof(int)*16);
memset(a,0,sizeof(a));
memset(a,0,4*16);
第2行和第3行代码效果是一样的,就是将整数数组a的每个元素初始化为0

这样写不论是16位编译器还是32位编译器,效果都是一样,不会产生歧义,不会造成访问越界。

而第4行就是是错误示例:开发者天真的以为int就一定是4字节。

一旦代码移植到诸如window ce或者其他可能存在16位编译器的环境,那结果就不敢去想——这种没有语法错误、没有明显逻辑错误、仅在某些环境下运行才能发现的错误是最可怕的。比这个更可怕的是这样的:

<pre name="code" class="cpp">int b,c,d,e;
int a[4];b=1,c=2,d=3,e=4;
memset(a,0,4*4);


执行完第4行之后,b、c、d、e可能被设置为0,而不是你想象中的1,2,3,4 。

要命的是这种错误没有任何征兆!!!

没有语法错误!没有编译错误!运行不会产生溢出!仅仅只有逻辑错误!

如果你本身就是要将b,c,d,e初始化为0,那就更可怕了,因为逻辑错误也不会有了。

但这是一颗潜伏的很好的炸弹,等到某天需求变更,a的长度由4变成5的时候,就会duang的一下爆发出来。

接手的人肯定还会奇怪,代码一直好好的,怎么长度变了一下就这鸟样了?

也许你会说,如果需求不变更就没有问题。

但是作为一个工作多年的程序员,我要和你说的是:

需求当中唯一不变的就是——需求一定会被改变!

今天到此为止,下次再见!


zerglurker的C语言教程010——运算符详解(三)

标签:c++   c语言   语言   编程   教程   

原文地址:http://blog.csdn.net/zerglurker/article/details/46529193

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!