《C++ Primer》学习笔记2
——2013.12.11周三第一周第二天 任务量:第二章(P29-P65)
- 对于 unsigned 类型来说,负数总是超出其取值范围。unsigned 类型的对象可能永远不会保存负数。有些语言中将负数赋给unsigned 类型是非法的,但在 C++ 中这是合法的。 C++ 中,把负值赋给 unsigned 对象是完全合法的,其结果是该负数对该类型的取值个数求模后的值。所以,如果把 -1 赋给8位的 unsigned char,那么结果是 255,因为 255 是 -1 对 256 求模后的值。
- 表 2.1. C++ 算术类型 short、int 和 long 类型都表示整型值,存储空间的大小不同。一般, short 类型为半个机器字长,int 类型为一个机器字长,而 long 类型为一个或两个机器字长(在 32 位机器中 int 类型和 long 类型通常字长是相同的)。类型 float、double 和 long double 分别表示单精度浮点数、双精度浮点数和扩展精度浮点数。一般 float 类型用一个字(32 位)来表示,double 类型用两个字(64 位)来表示,long double 类型用三个或四个字(96 或 128 位)来表示。类型的取值范围决定了浮点数所含的有效数字位数。
Type 类型 |
Meaning 含义 |
Minimum Size 最小存储空间 |
bool |
boolean |
NA |
char |
character |
8 bits |
wchar_t |
wide character |
16 bits |
short |
short integer |
16 bits |
int |
integer |
16 bits |
long |
long integer |
32 bits |
float |
single-precision floating-point |
6 significant digits |
double |
double-precision floating-point |
10 significant digit |
long double |
extended-precision floating-point |
10 significant digits |
- C++ 中整型数有点令人迷惑不解。就像 C 语言一样,C++ 被设计成允许程序在必要时直接处理硬件,因此整型被定义成满足各种各样硬件的特性。大多数程序员可以(应该)通过限制实际使用的类型来忽略这些复杂性。 实际上,许多人用整型进行计数。例如:程序经常计算像 vector 或数组这种数据结构的元素个数。在第三章和第四章中,我们将看到标准库定义了一组类型用于统计对象的大小。因此,当计数这些元素时使用标准库定义的类型总是正确的。其他情况下,使用 unsigned 类型比较明智,可以避免值越界导致结果为负数的可能性。
- 当执行整型算术运算时,很少使用 short 类型。大多数程序中,使用 short 类型可能会隐含赋值越界的错误。这个错误会产生什么后果将取决于所使用的机器。比较典型的情况是值“截断(wrap around)”以至于因越界而变成很大的负数。同样的道理,虽然 char 类型是整型,但是 char 类型通常用来存储字符而不用于计算。事实上,在某些应用中 char 类型被当作 signed 类型,在另外一些应用中则被当作 unsigned 类型,因此把 char 类型作为计算类型使用时容易出问题。
- 在大多数机器上,使用 int 类型进行整型计算不易出错。就技术上而言,int 类型用 16 位表示——这对大多数应用来说太小了。实际应用中,大多数通用机器都是使用和 long 类型一样长的 32 位来表示 int 类型。整型运算时,用 32 位表示 int 类型和用 64 位表示 long 类型的机器会出现应该选择 int 类型还是 long 类型的难题。在这些机器上,用 long 类型进行计算所付出的运行时代价远远高于用 int 类型进行同样计算的代价,所以选择类型前要先了解程序的细节并且比较 long 类型与 int 类型的实际运行时性能代价。
- 决定使用哪种浮点型就容易多了:使用 double 类型基本上不会有错。在 float 类型中隐式的精度损失是不能忽视的,而 double 类型精度代价相对于 float 类型精度代价可以忽略。事实上,有些机器上,double 类型比 float 类型的计算要快得多。long double类型提供的精度通常没有必要,而且还需要承担额外的运行代价。
- 20 // decimal 024 // octal 0x14 // hexadecimal
以 0(零)开头的字面值整数常量表示八进制,以 0x 或 0X 开头的表示十六进制。
- 字面值整数常量的类型默认为 int 或 long 类型。其精度类型决定于字面值——其值适合 int 就是 int 类型,比 int 大的值就是long 类型。通过增加后缀,能够强制将字面值整数常量转换为 long、unsigned 或 unsigned long 类型。定义长整型时,应该使用大写字母 L。小写字母 l 很容易和数值 1 混淆。通过在数值后面加 L 或者 l(字母“l”大写或小写)指定常量为 long 类型。类似地,可通过在数值后面加 U 或 u 定义 unsigned 类型。同时加 L 和 U 就能够得到 unsigned long 类型的字面值常量。但其后缀不能有空格: 128u /* unsigned */ 1024UL /* unsigned long */ 1L /* long */ 8Lu /* unsigned long */
- 通常可以用十进制或者科学计数法来表示浮点字面值常量。使用科学计数法时,指数用 E 或者 e 表示。默认的浮点字面值常量为double 类型。在数值的后面加上 F 或 f 表示单精度。同样加上 L 或者 l 表示扩展精度(再次提醒,不提倡使用小写字母l)。下面每一组字面值表示相同的值:
3.14159F .001f 12.345L 0.
3.14159E0f 1E-3F 1.2345E1L 0e0
在字符字面值前加 L 就能够得到 wchar_t 类型的宽字符字面值。如:L'a'
- 也存在宽字符串字面值,一样在前面加“L”,如 L"a wide string literal" 宽字符串字面值是一串常量宽字符,同样以一个宽空字符结束。
- 两个相邻的仅由空格、制表符或换行符分开的字符串字面值(或宽字符串字面值),可连接成一个新字符串字面值。这使得多行书写长字符串字面值变得简单:
// concatenated long stringliteral
std::cout << "amulti-line"
"string literal "
"usingconcatenation"
<< std::endl;
When executedthis statement would print:
执行这条语句将会输出:
a multi-line string literalusingconcatenation
- 如果连接字符串字面值和宽字符串字面值,将会出现什么结果呢?例如:
// Concatenating plainand wide character strings is undefined std::cout<< "multi-line " L"literal " << std::endl;
其结果是未定义的,也就是说,连接不同类型的行为标准没有定义。这个程序可能会执行,也可能会崩溃或者产生没有用的值,而且在不同的编译器下程序的动作可能不同。程序不应该依赖未定义行为。同样地,通常程序不应该依赖机器相关的行为,比如假定int 的位数是个固定且已知的值。我们称这样的程序是不可移植的。当程序移植到另一台机器上时,要寻找并更改任何依赖机器相关操作的代码。在本来可以运行的程序中寻找这类问题是一项非常不愉快的任务。
- C++ 的格式非常*。特别是有一些地方不能插入空格,其中之一是在单词中间。特别是不能在单词中间断开一行。但可以通过使用反斜线符号巧妙实现:
// ok: A \ before anewline ignores theline break
std::cou\
t <<"Hi" << st\
d::endl;
等价于std::cout << "Hi"<<std::endl;
可以使用这个特性来编写长字符串字面值:
// multiline string literal
std::cout << "amulti-line \
string literal \
using a backslash"
<< std::endl;
return 0;
}
注意反斜线符号必须是该行的尾字符——不允许有注释或空格符。同样,后继行行首的任何空格和制表符都是字符串字面值的一部分。正因如此,长字符串字面值的后继行才不会有正常的缩进。
- 强静态类型 C++ 是一门静态类型语言,在编译时会作类型检查。
- C++ 程序员常常把变量称为“变量”或“对象(object)”。 C++ 程序员经常随意地使用术语对象。一般而言,对象就是内存中具有类型的区域。说得更具体一些,计算左值表达式就会产生对象。在本书中,我们遵循更为通用的用法,即对象是内存中具有类型的区域。我们可以*地使用对象描述程序中可操作的大部分数据,而不管这些数据是内置类型还是类类型,是有名字的还是没名字的,是可读的还是可写的。
- 变量名,即变量的标识符,可以由字母、数字和下划线组成。变量名必须以字母或下划线开头,并且区分大小写字母:C++ 中的标识符都是大小写敏感的。
- 除了关键字,C++ 还保留了一些词用作各种操作符的替代名。这些替代名用于支持某些不支持标准C++操作符号集的字符集。它们也不能用作标识符。表 2.3列出了这些替代名。除了关键字,C++ 标准还保留了一组标识符用于标准库。标识符不能包含两个连续的下划线,也不能以下划线开头后面紧跟一个大写字母。有些标识符(在函数外定义的标识符)不能以下划线开头。
Table 2.3. C++ Operator Alternative Names 表 2.3. C++ 操作符替代名
and |
bitand |
compl |
not_eq |
or_eq |
xor_eq |
and_eq |
bitor |
not |
or |
xor |