1. 简单变量
1. 1 变量名命名规则:
- 在名称中只能使用字母字符、数字和下划线(_)。
- 名称的第一个字符不能是数字。
- 区分大写字符与小写字符。
- 不能将C++关键字用作名称。
- 以两个下划线或者下划线和大写字母打头的名称被保留给实现使用。
- C++对于名称的长度没有限制,名称中的所有字符都有意义,但有些平台有长度限制。
常用命名前缀有:str 或 sz(表示以空字符结束的字符串)、n(表示整型)、b(表示布尔值)、p(表示指针)和 c(表示单个字符)。
C程序员倾向于按C语言的方式使用下划线(如boar_sport, boats_port),而Pascal程序员喜欢采用大写方式(如carDrip, cardRip)。
1. 2 整型
基本整型包括 char, short, int, long 和 C++11新增的 long long。术语宽度(width)用于描述存储整数时使用的内存量。C++提供了一种灵活的标准,确保了最小长度(从C语言借鉴而来):
- short 至少16位。
- int 至少与 short 一样长。
- long 至少 32 位,且至少与 int 一样长。
- long long 至少 64 位,且至少与 long 一样长。
可以使用 sizeof 运算符返回类型或者变量的长度。
int i;
cout << sizeof i << endl;
cout << sizeof(i) << endl;
//以上 sizeof 的使用方法都是合法的
这四种类型(int、short、long 和 long long)都是符号类型,这意味着每种类型的取值范围中,负值和正值几乎相同。如 16 位的 int 的取值范围为 -32768 到 +32767。
头文件 climits 中包含了关于整型了限制的信息,定义了表示各种限制的符号名称:
符号常量 | 表示 |
---|---|
CHAR_BIT | char 的位数 |
CHAR_MAX | char 的最大值 |
CHAR_MIN | char 的最小值 |
SCHAR_MAX | signed char 的最大值 |
SCHAR_MIN | signed char 的最小值 |
UCHAR_MAX | unsigned char 的最大值 |
SHRT_MAX | short 的最大值 |
SHRT_MIN | short 的最小值 |
USHRT_MAX | unsigned short 的最大值 |
INT_MAX | int 的最大值 |
INT_MIN | int 的最小值 |
UNIT_MAX | unsigned int 的最大值 |
LONG_MAX | long 的最大值 |
LONG_MIN | long 的最小值 |
ULONG_MAX | unsigned long 的最大值 |
LLONG_MAX | long long 的最大值 |
LLONG_MIN | long long 的最小值 |
ULLONG_MAX | unsigned long long 的最大值 |
初始化
以下初始化方式都是合法的,大括号内可以不包含任何东西,在这种情况下,变量江北初始化为零。
int hamburgers = {24};
int emus{7};
int rheas = {12};
int rocs = {};
int psychics{};
1. 3 无符号类型
无符号类型不能存储负数值的无符号变体,可以增大变量能够存储的最大值。例如,如果 short 能表示的范围为-32768 到 +32768,则无符号版本的表示范围为0-65535。
上溢和下溢
以 short 和 unsigned short 为例:
(1)将两种变量初始化为 SHRT_MAX,分别 +1 后,short 变量的值从 +32767 变成了 -32768,unsigned short 变量的值增加 1。
(2)将两种变量初始化为 0 ,分别 -1 后,short 变量的值变成 -1,而unsigned short 的值变成了 65535。
实例代码:
short sam = SHRT_MAX;
unsigned short sue = sam;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl
<< "Add $1 to each account." << endl << "Now ";
sam += 1;
sue += 1;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited.\nPoor sam." << endl;
sam = 0;
sue = 0;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl
<< "Take $1 to each account." << endl << "Now ";
sam -= 1;
sue -= 1;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl << "Lucky Sue." << endl;
运行结果如下:
Sam has 32767 dollars and Sue has 32767 dollars deposited.
Add $1 to each account.
Now Sam has -32768 dollars and Sue has 32768 dollars deposited.
Poor sam.
Sam has 0 dollars and Sue has 0 dollars deposited.
Take $1 to each account.
Now Sam has -1 dollars and Sue has 65535 dollars deposited.
Lucky Sue.
1. 4 字面值
C++能以三种不同的技术方式来书写整数:基数为 10, 基数为 8 和基数为 16。C++使用前一(两)位来标识数字常量的基数。
- 如果第一位为 1~9,则基数为 10(十进制);
- 如果第一位是 0,第二位为 1~7,则基数为8(八进制);
- 如果前两位为 0x 或 0X,则基数为 16(十六进制),a~f 和 A~F 表示了十六进制位,对应于 10~15。
1. 5 char 类型
char 类型是另一种整型,能够表示目前计算机系统中的所有基本符号——所有的字母、数字、标点符号等。
在美国,最常用的符号及是 ASCII 字符集,其中的字符用数值编码(ASCII 码)表示。
cout.put()
cout 将字符变量显示为字符,而将字符常量显示为数字。
cout.put()可以用于显示字符常量
cout << '$'; // 将打印 $ 的ASCII码
cout.put('$'); // 将打印字符 $
C++ 转义序列的编码
字符名称 | ASCII 码 | C++ 代码 | 十进制 ASCII 码 | 十六进制 ASCII 码 |
---|---|---|---|---|
换行符 | NL(LF) | \n | 10 | 0xA |
水平制表符 | HT | \t | 9 | 0x9 |
垂直制表符 | VT | \v | 11 | 0xB |
退格 | BS | \b | 8 | 0x8 |
回车 | CR | \r | 13 | 0xD |
振铃 | BEL | \a | 7 | 0x7 |
反斜杠 | \ | \ | 92 | 0x5C |
问号 | ? | \? | 63 | 0x3F |
单引号 | ‘ | \’ | 39 | 0x27 |
双引号 | “ | \” | 34 | 0x22 |
注:在Mac OS平台,Xcode环境中,由于编译器是 LLVM,\b 和 \a 没有效果,使用 GCC 则效果正常。
使用 GCC 编译并运行 C++ 程序
使用 terminal 进入 .cpp 文件所在目录,运行如下命令:
编译并生成可执行文件:g++ xxx.cpp -o xxx
,xxx.cpp 为代码文件,-o
之后的 xxx 为自己命名的可执行文件。
在 terminal 运行上一步生成的可执行文件:./xxx
,xxx为上一步生成的可执行文件,
wchar_t
宽字符类型,可以表示系统使用的最大扩展字符集。
cin 和 cout 将输入和输出看作是 char 流,因此不适于用来处理 wchar_t 类型。 iostream 头文件的最新版本提供了作用相似的工具—— wcin 和 wcout,可用于处理 wchar_t 流。另外,可以通过加上前缀 L 来指示款字符常量和宽字符串。
wchar_t bob = L'P';
wcout << L"tall" << endl;
char16_t 和 char32_t
char16_t 为无符号,16 位;char32_t 为无符号,32 位。
使用前缀 u 表示 char16_t 字符常量和字符串常量。
使用前缀 U 表示 char32_t 字符常量和字符串常量。
char16_t ch1 = u'q';
char32_t ch2 = U'\U0000222B';
1. 6 bool 类型
bool 类型名称来源于英国数学家 George Boole,是他开发了逻辑律的数学表示法。布尔变量的值可以使 true 和 false。字面值 true 和 false 都可以通过提升转换为 int 类型,true 被转换为 1,false 被转换为 0。
int ans = true; // ans assigned 1
int promise = false; // promise assigned 0
C++ 会将非零值解释为true,将零解释为 false。
bool start = -100; // start assigned true
bool stop = 0; // stop assigned false
2. const 限定符
可以通过使用 const 关键字来修改变量声明和初始化,例如:
const int Months = 12; // Month 是一个值为 12 的符号常量
关键字 const 叫做限定符,因为它限定了声明的含义。
一种常见的做法是将名称的首字母大写,以提示此变量是一个常量。另一种约定是将整个名称都大写,使用 #define 创建常量时通常使用这种约定。
相对于 #define 的优点
- 能够明确指明类型。
- 可以使用 C++ 的作用于规则将定义限制在特定的函数或文件中。
- 可以将 const 用于更复杂的类型,如数组和结构。
注意:应该在声明中对 const 进行初始化
3. 浮点数
3. 1 书写浮点数
- 使用常用的标准小数点表示法:12.34
- E 表示法:2.52e+8,8.33E-4,7E5
注意:既可以使用 E 也可以使用 e,指数可以使整数也可以是负数,然而数字中有空格是非法的。
d.dddE+n 指的是将小数点向右移动 n 位,d.dddE-n 指的是将小数点向左移动 n 位。之所以称为“浮点数”,就是因为小数点可移动。
3. 2 浮点类型
分为三种:float、double、long double。
有效位数:float 至少 32 位;double 至少 48 位,且不少于 float;long double 至少和double 一样多。
指数范围至少是 -37 到 37。
float 和 double 表示数字时在精度方面存在差异,如下:
程序
cout.setf(ios_base::fixed, ios_base::floatfield);
float tub = 10.0 / 3.0;
double mint = 10.0 / 3.0;
const float million = 1.0e6;
cout << "tub = " << tub;
cout << ", a million tubs = " << million * tub;
cout << ",\nand ten million tubs = ";
cout << 10 * million * tub << endl;
cout << "mint = " << mint << " and a million mints = ";
cout << million * million * mint << endl;
运行结果如下:
tub = 3.333333, a million tubs = 3333333.250000,
and ten million tubs = 33333332.000000
mint = 3.333333 and a million mints = 3333333319680.000000
使用 ostream 方法 setf(),可以迫使输出使用定点表示法,防止程序把较大的值切换为 E 表示法,并使程序显示到小数点后 6 位。
3. 3 浮点常数
默认情况下,像 8.24 和 2.4E8 这样的浮点常数都属于 double 类型。如果希望常量为 float 类型,需使用 f 或 F 后缀。对于 long double 类型可以使用 l 或者 L 后缀。
1.234f // a float constant
2.45E20F // a float constant
2.345324E28 // a double constant
2.2L // a long double constant
3. 4 浮点数的优缺点
- 可以表示整数之间的值。
- 由于有缩放因子,可以表示的范围大很多。
- 浮点运算的速度通常比整数运算慢,且精度将降低。
4. C++ 算数运算符
+(加)、-(减)、*(乘)、/(除)、%(求模)
4. 1 类型转换
- 将一种算术类型的值赋给另一种算术类型的变量时,C++ 将对值进行转换;
- 表达式中包含不同的类型时,C++ 将对值进行转换;
- 将参数传递给函数时,C++ 将对值进行转换。
类型转换潜在的问题
转换 | 潜在的问题 |
---|---|
将较大的浮点类型转换为较小的浮点类型,如 double 转换为 float | 精度(有效位数)降低,值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的 |
将浮点类型转换为整型 | 小数部分丢失,原来的值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的 |
将较大的整型转换为较小的整型,如将 long 转换为 short | 原来的值可能超出目标类型的取值范围,通常只复制右边的字节 |
C++ 11 将使用大括号的初始化称为列表初始化。列表初始化不允许缩窄,也就是变量的类型可能无法表示赋给它的值。例如:不允许将浮点型转换为整型。在不同的整形之间转换或将整型转换为浮点型可能被允许。
整型提升
在自动转换中,计算表达式时,C++ 将bool、char、unsigned char、signed char 和 short 值转换为 int。如 true 被转换为 1,false 被转换为 0。
强制类型转换
强制类型转换的格式有两种。例如,为将存储在变量 thron 中的 int 值转换为 long 类型,可以使用下述表达式的一种:
(long) thron // returns a type long conversion of thron
long (thron) // returns a type long conversion of thron
通用格式如下:
(typeName) value // converts value to typeName type
typeName (value) // converts value to typeName type
4. 2 auto 声明
如果使用关键字 auto,而不指定变量的类型,编译器将把变量的类型设置成与初始值相同。
auto n = 100; // n is int
auto x = 1.5; // x is double
auto y = 1.3e12L; // y is long double
然而,自动推断类型并非为这种简单的情况而设计的,如果用于简单情况甚至可能出现问题。假如想要将x、y 和 z 都指定为 double 类型:
auto x = 0.0; // x is double because 0.0 is double
double y = 0; // 0 automatically converted to 0.0
auto z = 0; // z is int because 0 is int
处理复杂类型时,自动类型推断的优势才能显现出来,如:
C++ 98 代码:
std::vector<double> scores;
std::vector<double>::iterator pv = scores.begin();
C++ 11 允许将代码重写为:
std::vector<double> scores;
auto pv = scores.begin();
以上内容引用自人民邮电出版社《C++ Primer Plus》(第6版)