编写高质量代码:改善C++程序的150个建议(连载5)

发表于:2012-4-09 10:02

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:李健    来源:51Testing软件测试网采编

  C/C++语言标准支持第一种方式。这种方式不仅可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被同时包含。当然,其缺点就是如果一不小心在不同头文件中定义了相同的宏名,造成了宏名“撞车”,那就可能会导致明明看到头文件存在,编译器却硬说找不到声明,这确实会令人非常恼火。为了避免宏名“撞车”,保证宏的唯一性,建议按照Google公司建议的那样,头文件基于其所在项目源代码树的全路径而命名。命名格式为:

<PROJECT>_<PATH>_<FILE>_H_

  由于编译器在每次编译时都需要打开头文件才能判定是否有重复定义,因此在编译大型项目时,ifndef会使编译时间相对较长。

  #pragma once方式一般由编译器提供,它保证同一个文件不会被包含多次。这里所说的“同一个文件”指的是物理上的一个文件,而不是指内容相同的两个文件。#pragma once声明只针对文件,而不能针对某一文件中的一段代码。这种方式避免了因想方设法定义一个独一无二的宏而产生的烦恼;另外,针对大型项目的编译速度也有了提升。但是这种方式因为不受C/C++语言标准支持,所以受到了编译器的限制,它在兼容性方面表现得不是很好。因此很多程序员为了代码的兼容性,宁肯降低一些编译性能,而选择遵循C/C++标准,采用第一种方式。

  注意 针对#pragma once,GCC已经取消了对其的支持,而微软的VC++却仍在坚持。

  请记住:

  为了避免重复包含头文件,建议在声明每个头文件时采用“头文件卫士”加以保护,比如采用如下的形式:

  1. #ifndef _PROJECT_PATH_FILE_H_  
  2. #define _PROJECT_PATH_FILE_H_  
  3. ... ... // 声明、定义语句  
  4. #endif

  建议10:优化结构体中元素的布局

  下面的代码片段定义了结构体A和B:

  1. struct A  // 结构体A  
  2. {  
  3.       int a;  
  4.       char b;  
  5.       short c;  
  6. };  
  7. struct B  // 结构体B  
  8. {  
  9.       char b;  
  10.       int a;  
  11.       short c;  
  12. };

  在32位机器上,char、short、int三种类型的大小分别是1、2、4。那么上面两个结构体的大小如何呢?

  结构体A中包含了一个4字节的int,一个1字节的char和一个2字节的short,B也一样,所以A、B的大小应该都是4+2+1 = 7字节。但是,实验给出的却是另外的结果:

sizeof(strcut A) = 8, sizeof(struct B) = 12

  其原因还要从字节对齐说起。

  现代计算机中内存空间都是按照字节来划分的,从理论上来讲,对变量的访问可以从任何地址开始;但在实际情况中,为了提升存取效率,各类型数据需要按照一定的规则在空间上排列,这使得对某些特定类型的数据只能从某些特定地址开始存取,以空间换取时间,这就是字节对齐。

  结构体默认的字节对齐一般满足三个准则:

  (1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除。

  (2)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员自身大小的整数倍,如有需要,编译器会在成员之间加上填充字节(Internal Adding)。

  (3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(Trailing Padding)。

32/3<123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号