C++ 类型和声明

4.1 保持较小的作用域。

保持较小的作用域有助于避免一些难以发现的错误。

C++支持在for循环和if语句中直接声明变量,如:

for (int i=0; i<100;i++){}

if (bool b = func() ) {}

其中i和b的作用域从被声明的点开始,直到 } 结束。

4.2 不要在一个作用域和它外围的作用域里采用同样的名字。

在一个作用域和它外围的作用域里采用同样的名字会造成名字遮蔽,即外围的名字被内部作用域的名字遮蔽,人们很容易没有注意某个名字被遮蔽了,所以会造成一些隐蔽的错误。

4.3 在一个声明中声明一个名字。

例如int* p, q; 是指int* p; int q; 而不是int* p; int* q;  int* p, q;这种结构不利于阅读,因此应该避免。

4.4 让常用的和局部的名字比较短,让不常用的和全局的名字比较长。

选择好的名字是一种艺术。较大的作用域的名字应该相对比较长且更加明确,如textParser、intMatrix。在很小的作用域使用很短且熟悉的名字,如i、x、tmp。常用的名字比较短,书写方便,不常用的名字比较长这种做法也很有价值。

4.5 避免看起来类似的名字。

如只是大小写不同的名字,count和Count。或者大写的O和零0,小写的L(l)和一(1)都很难分辨,应该避免。一些代码分析工具如CodeWizard会对它们提出警告。

4.6 维持某种统一的命名风格。

应该选择一种统一的命名风格。如宏定义和枚举大写,用下划线分隔单词等。这样可以提高代码的可读性。

4.7仔细选择名字,反映其意义而不是反映其实现方式。

例如phone_book就比number_list要好,即使你的电话号码实际存放在list里。请仔细选择那些重要的名字,否则几个月后自己写的代码也会让你困惑。

4.8如果所用的内部类型表示某种可能变化的值,请用typedef为它定义一个有意义的名字。

例如我们想用float去表示温度,那么用typedef会清晰的表明含义。typedef float Temperature。Temperature temp;

4.9 用typedef为类型定义同义词,用枚举或类定义新类型。

typedef是为类型定义同义词,而不是定义新的类型。C++里只有枚举或类是用户定义类型,可以用来定义新类型。

4.10 切记每个声明中都必须描述一个类型(没有“隐式的int“)

例如const c = 7;C和C++的早期版本将int作为没有明确声明的类型。这种隐式的int会导致许多微妙错误。

4/11 避免有关字符数值的不必要假设。

一个字符表示的是C++程序运行的机器上的字符集中该字符的整数值。如果在一台使用ASCII字符集的机器上,’0’的值就是48。在非ASCII字符集的机器上如EBCDIC字符集,’0’的值是240。char的大小通常为8位,但标准并没有规定它的大小,只是保证至少有8位。

4.12避免有关整数大小的不必要假设。

int的大小是由实现确定的,典型情况下是32位。short int至少有16位,long int至少有32位。

4.13避免有关浮点类型表示范围的不必要假设。

浮点类型有float、double、long double,它们的大小由实现确定。

4.14 优先使用普通的int而不是short int 或者long int

int大小由实现选择,采用在给定的计算机上最适合存储和操作整数的类型,通常是一个32位的机器字。

4.15 优先使用double而不是float 或者long double

浮点类型有float、double、long double,意义由实现确定。对浮点运算的深入理解能帮助选择合适的类型,或者一般情况下选择double就可以。

4.16 优先使用普通的char而不是signed char 或者unsigned char

char可能是有符号的,也可能是无符号的。这三种char类型的变量可以相互赋值,但可能导致无定义的结果。例如,char c; signed char sc; unsigned char uc;

c = 255; // 如果char有符号且为8位,则由实现定义

c = sc; // 可以

c = uc; //如果普通char有符号且uc值过大,则由实现定义

sc = uc; //uc值过大,则由实现定义

uc = sc;//可以, 转换到unsigned值

sc = c; ///如果普通char无符号且c值过大,则由实现定义

uc = c; //可以, 转换到unsigned值

如果始终采用普通char, 这些问题都不会出现。

4.17 避免做出有关对象大小的不必要假设。

C++对象的大小是用char的大小的倍数表示的, 按照定义,char的大小为1。

基本类型大小的性质为:

1=sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)

1 <= sizeof(bool) <= sizeof(long)

sizeof(char) <= sizeof(wchar_t) <= sizeof(long)

sizeof(float) <= sizeof(double) <= sizeof(long double)

sizeof(N) = sizeof(signed N) = sizeof(unsigned N)

4.18 避免无符号算术。

通过将变量声明为unsigned而保证某些值始终为正的企图常常被隐含的类型转换规则破坏。如有这样的定义,unsigned int ui; int i; 如果恰好ui的值为0 且 i的值为-1,那么ui+i等于多少? -1?结果将是unsigned int类型的最大值。因为i会被提升到unsigned int,然后再与ui相加。 如果是两个普通的int相加就不会有问题。

4.19 应该带着疑问去看待从signed到unsigned,或者从unsigned到signed的转换。

如果目标类型是unsigned,结果值就是从原值中取出正好等于目标类型所需要的那么多位, 可能会发生截断。 如unsigned char uc = 1023;高位被截断, uc的值为255,即11111111。

如果目标类型是signed,如果源值在结果类型中可以表示,则值不变,否则结果值由实现定义。 如signed char sc = 1023;//实现定义

4.20应该带着疑问去看待从浮点到整数的转换。

浮点到整数转换,小数部分将被丢掉,也就是截断。如果转换结果无法在目标类型里表示,则结果无定义。 如:int i = 2.7;//i变为2

char b = 2000.7;// 对8位char无定义,2000不能在8位char里表示

4.21应该带着疑问去看待向较小类型的转换,如将int转到char。

向较小类型的转换,如将int转到char, 可能发生截断, 也可能导致无定义的行为, 参考4.19

时间: 2024-12-15 01:40:37

C++ 类型和声明的相关文章

限制泛型可用类型,类型通配符声明,泛型方法

一.限制泛型可用类型 ①   在定义泛型类型时,默认在实例化泛型类的时候可以使用任何类型,但是如果想要限制使用泛型类型时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个类; ②   当没有指定泛型继承的类型或接口时,默认使用extends Object,所以默认情况下任何类型都可以作为参数传入; 继承抽象类 1 public class GenericDemo3{ 2 public static void

菜鸡的swift学习(1):Mac中语言设定,no such module Cocoa的,可选类型的声明

Mac中语言的设定: no such module Cocoa:在试一下swift的教程学习的代码的时候 发现import Cocoa导入这个包的时候一直报错 因为我新建的是playground的工程,所以应该导入UIkit包这样就可以解决这个错误 Cocoa这个包是在IOS开发中使用的包 可选类型的声明时 var myString:String ?= nil 注意空格 原因是我没有注意到'?'和空格的位置 修正为 var myString:String? = nil String?中间是没有空

1.枚举类型、声明指针、常量、存储类型、运算符优先级记忆

原文:1.枚举类型.声明指针.常量.存储类型.运算符优先级记忆 1.枚举类型 枚举(enumerated)类型就是指它的值为符号常量而不是字面值的类型,以下面的这种形式来声明:enum   Jar_Type {CUP,PINT,GALLON,OUART}; 这条语句声明了一个类型,称为 Jar_Type.而enum  {CUP,PINT,GALLON,OUART}; 这条语句声明表示这种类型的变量以整型的方式存储,这些符号名的实际值都是整型值.这里CUP是0,PINT是1,以此类推.下面看一下一

C++笔记第四章--类型和声明

布尔量 Eg: bool b1=a==b;//这个例子中,=是赋值,==是判断是否相等,所以先是判断是否相等,a如果等于b,b1的值就是true,否则就是false了 Bool经常被用作检查某些条件是否成立的函数的结果类型, Eg:bool greater(int a,int b) {return a>b} Bool可以和整数进行隐式的转换(任何非零的整数都是true,零为false) eg:bool a=ture; bool b=true; bool x=a+b;//因为a+b=2 为true

类型和声明笔记

后缀的声明运算符比前缀的那些声明运算符约束力更强,因此,*kings[]就是一个指向什么东西的指针数组 可以有多个声明,重复的 若声明多个相同名字,局部的在作用域里优先 如果没有提供初始化,则全局的.名字空间的和局部静态的对象将会被自动初始化为适当类型的0.局部的不会

结构体类型重声明导致的bug一个

bug前提条件 当模块比较多,头文件较多,某个结构体类型会在当前模块中重新声明进而引用其成员,而不直接包含其他模块的头文件.这样的好处是不引入不需要的类型声明到此模块,头文件包含的交叉:坏处是,增加了bug的几率,耦合太大!比如下面一种情况发生而导致bug: 已知两个模块A和B,同一个结构类型struct node在两个模块中分别声明,其中B模块无意或者有意调整了结构类型中的某些域.那么这个时候,若B模块中引用A模块中此类型实例然后访问成员变量,就会引发bug!如下重现示例 bug重新示例代码

枚举类型的声明

namespace c编程练习题 { public enum Seasons //在域名区域声明枚举类型 Seasons.方便团队开发. { 春, 夏, 秋, 冬, } class Program { static void Main(string[] args) { Seasons s = Seasons.春; //声明一个枚举类型s.

The C++ Programming Language 学习笔记 第四章 类型和声明

1.关于main 函数中的 return 0 C99标准中,main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的激活者(如操作系统).如果 main 函数的最后没有写 return 语句的话,C99 规定编译器要自动在生成的目标文件中(如 exe 文件)加入return 0; ,表示程序正常退出.尽管如此有人会为了移植性在main函数后面加上return 0,这是为了照顾老版本的编译器,如vc6.0等,不过现在过了这么多年了,应该没有人会用这么老的编译器了吧(也许不一定),所以

Function类型-函数声明与函数表达式

实际上,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁.解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问):至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行.请看下面的例子: alert(sum(10,10)); function sum(num1,num2){ return num1+num2; } 以上代码完全可以正常运行.因为在代码执行之前,解析器就已经通过一个名为函数声明提升(function declaration hoist