C语言中容易被忽略的细节(第二篇)

转载时自己也能回顾一遍,所以还是有必要转载的。

前言:本文的目的是记录C语言中那些容易被忽略的细节。我打算每天抽出一点时间看书整理,坚持下去,今天是第一篇,也许下个月的今天是第二篇,明年的今天又是第几篇呢?……我坚信,好记性不如烂笔头。


第一篇链接:C语言中容易被忽略的细节(第一篇)

第三篇链接:C语言中容易被忽略的细节(第三篇)

第四篇链接:C语言中容易被忽略的细节(第四篇)


1、C语言中只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来。C语言中数组元素可以是任何对象,也可以是另外一个数组,即数组的数组。


2、C语言允许初始化列表出现多余的逗号。例如:int days[] = {1,2,3,};作用:方便自动化生成代码。


3、因为a[i]与*(a + i)等价,且由于a+i与i+a的含义一样,因此a[i]与i[a]具有相同含义。


4、在使用运算符“&&”的表达式中,要尽量把最有可能为false的子表达式放在“&&”左边;在使用运算符“||”的表达式中,要尽量把最有可能为true的子表达式放在“||”左边。因为C/C++对逻辑表达式的判断采取“猝死法”:如果“&&”左边的子表达式计算结果为false,则整个表达式就为false,后面的子表达式没有必要再计算;如果“||”左边的子表达式计算结果为true,则整个表达式就为true,后面的子表达式没有必要再计算。这种方法可提高程序效率。


5、对于多维数组来说,正确的遍历方法要看语言以什么顺序来安排数组元素的存储空间。对于C/C++多维数组来说,“先行后列”遍历效率肯定好于“先列后行”遍历,不管其行数远大于列数还是情况相反甚至接近。影响效率的实际上主要是大型数组导致的内存页面交换次数及cache命中率的高低,而不是循环次数本身。


6、为什么fgetc()函数返回值为int而不是unsigned char?

函数调用出错或读到文件末尾时fgetc()会返回EOF,即-1。若EOF保存在unsigned char型中,结果为0xff,而0xff是ASCII码有意义的字节,因而将无法区分是字节0xff还是结束符EOF。若EOF保存在int型中,结果为0xffffffff,如果读到字节0xff,转换为int型为0x000000ff,能够正确区分EOF和字节0xff。


7、如果函数没有参数,应使用void而不要空着,因为标准C把空的参数列表解释为可以接受任何类型和个数的参数,而标准C++则把空的参数列表解释为不可接受任何参数。在移植C/C++程序时,尤其要注意这方面的不同。


8、在函数体的“出口处”,对return语句的正确性和效率进行检查。

(1)return语句不可返回“堆栈内存”的“指针”或“引用”,因为该内存单元在函数体结束时被自动释放。

[cpp]  view plain copy
  1. //存在隐患的写法    
  2. char *Func(void)    
  3. {    
  4.     char str[] = "hello world";    
  5.     return str;     //该语句存在隐患,str指向的内存单元将被释放    
  6. }    
  7.     
  8. //可行的写法    
  9. const char *Func(void)    
  10. {    
  11.     const char *p = "hello world";    
  12.     return p;       //返回字符串常量的地址    
  13. }    

(2)如果函数返回值是一个对象,要考虑return语句的效率。

[cpp]  view plain copy
  1. return string(s1 + s2);     //语句1  
  2.   
  3. string result(s1 + s2);     //语句2   
  4. return result;   

语句1与语句2并不等价。语句1表示创建一个临时对象并返回它。语句2执行了三件事:

1)result对象被创建,调用相应的构造函数初始化;

2)调用拷贝构造函数,把result复制到保存返回值的外部存储单元中。

3)result在函数结束时调用析构函数被销毁。

注意:创建临时对象并返回它,编译器可直接把临时对象创建并初始化在外部存储单元中,省去了拷贝和析构的开销,提高了效率。内部数据类型变量不存在构造函数和析构函数,采用创建临时变量并返回,不会提高多少效率,但会使程序更加简洁。例如:

[cpp]  view plain copy
  1. int x, y;  
  2. return x + y;    


9、不要省略返回值的类型,如果函数没有返回值,应声明为void类型。在标准C语言中,凡是不加类型说明的函数,一律自动按int类型处理。这样做不会有什么好处,却容易被误解为返回void类型。C++语言有严格的静态类型安全检查,不允许上述情况发生。由于C++程序可以调用C函数,为了避免混乱,我们规定任何C/C++函数都必须有返回值类型。


10、如果参数是指针,且仅做输入用,则应在类型前加const,以防止该指针指向的内存单元在函数体内无意中被修改。如果输入参数以值传递的方式传递对象,改用“const &”方式来传递,因为引用的创建和销毁不会调用对象的构造和析构函数,从而可提高效率。

转载自:http://blog.csdn.net/mengwang024/article/details/40450143
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值