C++秃头之旅:简单变量
程序通常都需要存储信息,为把信息存储在计算机中,程序必须经历3个基本属性:
- 信息将存储在哪里?
- 要存储什么值?
- 存储何种类型的信息?
声明中是使用的类型描述了信息的类型和通过符号来表示其值的变量名,例如下面代码所示:
int braincount; braincount = 5;
这些语句告诉程序,他正在存储整数,并使用名称 braincount 来表示该整数的值(这里为5)。实际上程序将找到一块能够存储整数的内存,将该内存标记为 braincount ,并将5复制到该内存单元中;然后你可在程序中使用 braincount来访问该内存单元。可使用 & 运算符来检索 braincount的内存地址。
变量名:
-
C++提倡使用一定含义的变量名。必须遵循几种简单的C++命名规则:
- 在名称中只能使用字母字符、数字和下划线(_)
- 名称中的第一个字符不能是数字
- 区分大写字符与小写字符
- 不能将C++关键字用作名称
-
以两个下划线或下划线和大写字母打头的名称被保留该实现(编译器及其使用的资源)使用;以一个下划线开头的名称被保留给实现,用作全局标识符
- 这点与前几点有所不同,因为使用像 _time_stop 或 _Donut 这样的名称不会导致编译器错误,而会导致行为的不确定性;换句话说,不知道结果将会是什么。
- 不出现编译器错误的原因是,这样的名称不是非法的,但要留给实现使用。
- 全局名称指的是名称被声明的位置。
- C++对于名称的长度没有限制,名称中所有的字符都有意义,但有些平台有长度限制
- 如果想用或两个更多的单词组成一个名称,通常的做法是用下划线字符将单词分开,如 my_onions ;或者从第二个单词开始讲两个单词的第一个字母大写,如 myEyeTooth。(推荐使用下划线风格)
-
可在变量名中加入描述变量类型或内容前缀,例如:
- 可以将整形变量 myWeight 命名为 nMyWeight ,其中前缀n用来表示整形值
- 长以这种方式使用的其他前缀有:str 或 sz (表示以空字符结束的字符)、b(表示布尔值)、p(表示指针)、和 c (表示单个字符)
整形:
- 整数就是没有小数部分的数字。
- 整数有很多,如果将无限大的整数看做很大,则不可能用有限的计算机内存来表示所有整数,因此语言只能表示所有整数的一个子集
- 不同C++整形所有的不同的内存量来存储整数。使用的内存量越大,可以表示的整数整数值范围也就越大。另外有的类型(符号类型)可表示正值和负值,而有的类型(无符号类型)不能表示负值。
- 术语宽度用于描述存储整数时使用的内存量。使用的内存越多,则越宽。
-
C++的基本整形(按宽度递增的顺序排列)分别是 char 、short 、int 、long 、和C++新增的long long,其中每种类型都有符号版本和无符号版本,因此总共有10中类型可供选择。
- 实际上,short是short int 的简称,而 long 是 long int 的简称
-
这4中类型都是符号整形(short 、int 、long、long long)都是符号整形,这意味着每种类型的取值范围中,负值和正值几乎相同。
- 例如:16位的 int 的取值范围为-32768~+32768
- 由于 char 类型有一些特殊性,所以它最常用来表示字符,而不是数字
整形 short、int 、long、和 long long:
- 计算机内存由一些叫做位(bit)的单元组成。
- C++的short,Int,long和long long类型通过使用不同数目的位来存储值,最多能够表示4种不同的整数宽度。如果在所有的系统中,每种类型的宽度都相同,则使用起来将非常方便。例如,如果short总是16位,int 总是32位,这将非常方便。
-
C++提供了一种灵活的标准,它确保了最小长度(从C语言借鉴而来),如下所示:
- short 至少16位
- int 至少与 short 一样长
- long 至少 32位,且至少与 int一样长
- long long至少64位,且至少与 long 一样长
-
位与字节
- 计算机内存的基本单元是位(bit)。可以将位看作电子开关,可以开,也可以关。关表示值0,开表示值1。
- 8位的内存块可以设置出256种不同的组合,因为每一位都可以有两种设置,所以8位的总组合数为2x2x2x2x2x2x2x2,即256。因此,8位单元可以表示0~255或者-128~127。每增加一位,组合数便加倍。这意味着可以把16位单元设置成65536个不同的值,把32位单元设置成4294672296个不同的值,把64位单元设置为44674073709551616个不同的值。作为比较,unsignedlong存不了地球上当前的人数和银河系的星星数,而long long能够。
- 字节(byte)通常指的是8位的内存单元。从这个意义上说,字节指的就是描述计算机内存量的度量单位,IKB等于1024字节,IMB等于1024KB。然而,C++对字节的定义与此不同。C++字节由至少能够容纳实现的基本字符集的相邻位组成,也就是说,可能取值的数目必须等于或超过字符目。在美国,基本字符集通常是ASCII和EBCDIC字符集。它们都可以用8位来容纳,所以在使用这两种字符集的系统中,C++字节通常包含8位。有些人使用术语8位组表示8位字节。
-
sizeof 运算符返回类型或变量的长度,单位为(字节);头文件 climits 包含了关于整数限制的信息,定义了表示各种符号名称
-
程序示例:
// 一些整数限制 #include <iostream> #include <climits> using namespace std; int main() { int n_int = INT_MAX; short n_short = SHRT_MAX; long n_long = LONG_MAX; long long n_llong = LLONG_MAX; cout << "int is " << sizeof(int) << " bytes." << endl; cout << "short is " << sizeof n_short << " bytes." << endl; cout << "long is " << sizeof n_long << " bytes." << endl; cout << "long long is " << sizeof n_llong << " bytes." << endl; cout << endl; cout << "Maximum values:" << endl; cout << "int:" << n_int << endl; cout << "short:" << n_short << endl; cout << "long:" << n_long << endl; cout << "long long:" << n_llong << endl << endl; cout << "Minimum int value = " << INT_MIN << endl; cout << "Bits per byte = " << CHAR_BIT << endl; cin.get(); return 0; }
程序输出:
int is 4 bytes.
short is 2 bytes.
long is 4 bytes.
long long is 8 bytes.
Maximum values:
int:2147483647
short:32767
long:2147483647
long long:9223372036854775807
Minimum int value = -2147483648
Bits per byte = 8
-
运算符sizofe 和头文件 limits
-
sizeof 运算符指出,在使用8位字节的系统中,int长度为4个字节。可对类型名或变量名使用sizeof运算符。
-
对类型名(如int)使用sizeof运算符时,应将名称放在括号中;但对变量名使用该运算符时,括号是可选的:
cout << "int is " << sizeof(int) << " bytes." << endl; cout << "short is " << sizeof n_short << " bytes." << endl;
-
-
头文件climits定义了符号常量来表示类型的限制。例如:
- INT_MAX表示类型int能够存储的最大值
-
编译厂商提供了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 的最大值 |
-
符号常量——预处理方式
-
climits文件中包含与下面类似的语句行:
#define INT_MAX 32767
在C++编译过程中,首先将源代码传递给预处理器。在这里,#define和#include一样,也是一个预处理器编译指令。
该编译指令指令高速预处理器:在程序中查找INT_MAX,并将所有的INT_MAX都替换为32767。
但C++有一种更好创建符号常量的方法:使用关键字const。
-
-
初始化
-
初始化将赋值与声明合并在一起,例如,下面的语句声明了变量n_int,并将int的最大取值赋给它:
int n_int = INT_MAX;
也可以使用字面常量来初始化。可以将变量初始化另一个变量,条件是后者已经定义过。甚至可以使用表达式来初始化变量,条件是所有值都是已知的
int uncles = 5; int aunts = uncles; int chairs = aunts + uncles + 4;
前面的初始化来自C语言,C++还有另一种C语言没有的初始化语法:
int owls = 101; int wrens(432); //C++独有的变量初始化语法
- 注意:如果不对函数内部定义的变量进行初始化,该变量的值将是不确定的。这意味着该变量的值将是他被创建之前,相应内存单元保存的值
-
-
C++11初始化方式
-
还有另一种初始化方式,这种方式用于数据和结构,但在C++98中,也可用于单值变量:
int hamburgers = (24);
将大括号初始化器用于单值变量的情形还不多,但C++11标准使得这种情形更多了。首先,采用这种方式时,可以使用等号(=),也可以不使用:
int emus{7}; int rheas = {12};
其次,大括号内可以不包含任何东西。在这种情况下,变量将被初始化为0:
int rocs {}; int psychics{}; //将被初始化为0
-
注意:这种方法助于更好地防范类型转换错误
-
-
无符号类型:
-
前面介绍的4种整形都有一种不能存储负数值的无符号变体,其优点是可以增大变量能够存储的最大值,例如:
- short表示范围为-32768~+32768,则无符号版本表示范围为0~65536
-
要创建无符号版本的基本整形,只需使用关键字unsigned来修改声明即可:
unsigned short change; unsigned int rovert; unsigned quarterback; //也是 unsigned int unsigned long gone; unsigned long long lange_lange
- 注意:unsigned 本身是unsigned int 的缩写
-
程序示例:
//超过一些整数限制 #include <iostream> #include <climits> //头文件climits定义了符号常量来表示类型的限制 #define ZERO 0 //将0符号设置为ZERO符号 using namespace std; int main() { short sam = SHRT_MAX; // 查看 short 的最大值 unsigned short sue = sam; //将 short 的最大值赋值给无符号的 short cout << "Sam has " << sam << " dollars and Sue has " << sue; cout << " dollars deposited." << endl << "Add $1 to each account." << endl << "Now";
sam = sam + 1; sue = sue + 1;
cout << " Sam has " << sam << " dollsrs and Sue has " << sue; cout << " dollars deposited.\npoor Sam!" << endl;
sam = ZERO; sue = ZERO;
cout << "Sam has " << sam << " dollsrs and Sue has " << sue; cout << " dollars deposited." << endl << "Take $1 to each account." << endl << "Now";
sam = sam - 1; sue = sue - 1;
cout << " Sam has " << sam << " dollsrs and Sue has " << sue; cout << " dollars deposited." << endl << "lucky Sue!" << endl; cin.get(); return 0; }程序输出:
Sam has 32767 dollars and Sue has 32767 dollars deposited.
Add $1 to each account.
Now Sam has -32768 dollsrs and Sue has 32768 dollars deposited.
poor Sam!
Sam has 0 dollsrs and Sue has 0 dollars deposited.
Take $1 to each account.
Now Sam has -1 dollsrs and Sue has 65535 dollars deposited.
lucky Sue!
-
该程序将一个short变量(sam)和一个unsigned short 变量(sue)分别设置为最大的short值;然后将这些变量的值+1。
-
从结果可以看出,这些整形变量的行为就行里程表,如果超过了限制,其值将为范围另一端的取值。C++确定保了无符号类型的这种行为;但C++并不保证符号整形超过限制(上溢和下溢)是不出错,而正是当前实现中最为常见的行为。
-
选择整型类型:
-
自然长度指的是计算机处理起来效率最高的长度,如果没有非常有说服力的理由来选择其他类型,则应使用int。
- 通常,int被设置为对目标计算机而言,最为自然的长度。
- 如果变量表示的值不可能为负数,则可以使用无符号类型,这样变量可以表示更大的值
-
如果知道变量可能表示的整数值大于16位整数的最大可能值,则使用long。即使系统上Int为32位,也应这样做。
- 这样将系统移植到16位系统时,就不会突然无法正常工作
- 如果存储的值超过20亿,可使用long long
-
如果short比int小,则使用short可以节省内存
- 通常,仅当有大型整型数组时,才有必要使用short。
- 如果只需要一个字节,可使用char
整型字面值:
-
整型字面值(常量)是显示地书写的常量,与C相同,C++能够以3种不同的计数方式来书写整数
- 10进制
- 8进制
- 16进制
-
表示法:
-
C++使用前一(两)位来标识数字常量的进制:
- 如果第一位为 1~9,则为10进制——因此93是10进制
- 如果第一位是 0,第二位为1~7,则为8进制——因此042是8进制
- 如果前两位为 0x 或 0X,则为16进制——因此0x42为16进制
-
-
程序示例:
//显示16进制和8进制文字 #include <iostream> using namespace std; int main() { int chest = 42; int waist = 0x42; int inseam = 042;
cout << "Monsieur cuts a striking figure!\n"; cout << "chest = " << chest << " (42 in decimal)\n"; cout << "waist = " << waist << " (0x42 in hex)\n"; cout << "inseam = " << inseam << " (042 in octal)\n"; cin.get(); return 0; }程序输出:
Monsieur cuts a striking figure!
chest = 42 (42 in decimal)
waist = 66 (0x42 in hex)
inseam = 34 (042 in octal)
- 注意:在默认情况下,ocut 以十进制格式显示整数,而不管这些整数在程序中是如何书写的
- 这些表示方法仅仅是为了表达上的方便。但是不管把值书写为10、012还是0xA,都将以相同的方式存储在计算机中——被存储为2进制数
-
如果要以16进制或8进制方式显示值,则可使用cout的一些特殊性:
-
可使用头文件iostream提供的控制符:
-
dec
- 十进制
-
hex
- 十六进制
-
oct
- 八进制
-
-
程序示例:
//以16进制和8进制显示值 #include <iostream> using namespace std; int main() { int chest = 42; int waist = 42; int inseam = 42;
cout << "Monsieur cuts a striking figure!" << endl; cout << "chest = " << chest << " (decimal for 42)" << endl; cout << hex << "waist = " << waist << " (hexadecimal for 42)" << endl; cout << oct << "inseam = " << inseam << " (octal for 42)" << endl; cin.get(); return 0; }程序输出:
Monsieur cuts a striking figure!
chest = 42 (decimal for 42)
waist = 2a (hexadecimal for 42)
inseam = 52 (octal for 42)
- cout << hex;等代码修改了cout显示整数的方式
- 注意:由于标识符hex位于名称空间std中,而程序使用了该名称空间,因此不能将hex用作变量名。然而,省略编译指令using,而是用std::hex,则可以使用hex做变量名
-
C++如何确定常量的类型
-
假设在程序中使用常量表示一个数字
cout << "Year = " << 1492 << endl;
- 在C++中,除非有理由存储为其他类型,否则C++将整型存储为int类型
-
后缀
-
后缀是放在数字常量后面的字母,用于表示类型。
- 整数后面的l或L后缀表示该整数为long常量
- u或U后缀表示unsignedint常量
- ul(可以采用任何一种顺序,大写小写均可)表示unsigned long 常量(由于小写 l 看上去像1,因此应使用大写L作后缀)
-
例如:
- 数字22022被存储为int,占16位
- 数字22022L被存储为long, 占32位
- 22022LU和22022UL都被存储为unsigned long
- C++11提供了用于表示类型long long 的后缀 ll 和 LL
- 用于表示类型 unsigned long long 的后缀ull、Ull、uLL和ULL
-
-
长度
- 十六进制数0x9c40 (4000) 将被表示为unsigned int。这是因为十六进制常用来表示内存地址,而内存地址是没有符号的,因此 usigned int比 long更适合用来表示16位的地址
char 类型:字符和小整数
- char类型是专为存储字符(如字母和数字)而设计的。
- char类型是另一种整型。它足够长,能够表示目标计算机系统中的所有基本符号——所有的字母、数字、标点符号等。
- 虽然char最常被用来处理字符,但也可以将它用作比short更小的类型
-
程序示例:
// char类型 #include <iostream> using namespace std; int main() { char ch; cout << "Enter a character: " << endl; cin >> ch; cin.get(); cout << "Thank you for the " << ch << " character." << endl; cin.get(); return 0; }
程序输出:
Enter a character:
A
Thank you for the A character.
- 注意:输入时,cin将键盘输入的A转换为65,输出时,cout将值65转换为所显示的字符A
-
下面程序引入了cout的一项特性——cout.put()函数,该函数显示一个字符。
//对比char类型和int类型 #include <iostream> using namespace std; int main() { char ch = 'M'; int i = ch; cout << "The ASCII code for " << ch << " is " << i << endl; cout << "Add one to the character code:" << endl; ch = ch + 1; i = ch; cout << "The ASCII code for " << ch << " is " << i << endl;
//使用cout.put()成员函数显示char cout << "Displaying char ch using cout.put(ch): "; cout.put(ch); //使用count.put()函数来显示char常量 cout.put('!'); cout << endl << "Done" << endl;
cin.get(); return 0; }程序输出:
The ASCII code for M is 77
Add one to the character code:
The ASCII code for N is 78
Displaying char ch using cout.put(ch): N!
Done
-
程序说明:
- 在程序中,’M’表示字符M的数值编码,因此将char变量ch初始化’M’,将把 i 变量这只为77。
- 值的类型将引导cout选择如何显示值——这是智能对象的另一个例子
-
即使通过键盘输入的数字也被视为字符
char ch; cin >> ch;
-
如果输入5并按回车,上述代码将读取字符’5’,并将其对应的ASCII码存储到变量ch中
int n; cin >> n;
- 如果输入5并按回车,上述代码将读取字符’5’,将其转换为相应的数字值5,并存储到变量n中
-
-
成员函数
- 函数cout.put()是一个重要的C++OOP概念——成员函数
-
成员函数归类所有,描述了操纵类数据的方法。要通过对象(如cout)来使用成员函数,必须用句点将对象名和函数名称put()连接起来。意思是:
- 通过类对象cout来使用函数put()
- 句点被称为成员运算符。
-
char字面值
- 在C++中,对于常规字符(如字母、标点符号和数字),最简单的方法是将字符用单引号括起,这种表示方法代表的是字符的数值编码
- C++还提供了一种特殊的表示方法——转移序列
-
换行符可替代endl,用于在输出中重起一行。下面3行代码都将光标移到下一行开头:
cout << endl; cout << '\n'; cout << "\n";
-
可以将换行符嵌入到字符串中,这通常比使用endl方便
cout << endl <<endl << "然后呢?" << endl << "没然后了" << endl; cout << "\n\n然后呢?\n没然后了\n";
-
显示数字时,使用endl比输入“\n“或‘\n’更容易些,但显示字符串时,在字符串末尾添加一个换行符所需的输入量更少些
cout << x << endl; cout << "我是一个字符串\n";
-
可以基于字符的8进制和16进制编码来使用转义序列
-
例如字母M的ASCII码为77,对应的8进制数为115,16进制数为0x4d,可以用下面的转义字符来表示该字符:\0115或\x4d。将这些编码用单引号或双引号括起。可以得到相应的字符常量
- 注意:在可以使用数字转义序列或符号转义序列(如\0x8 和 \b)时,应使用符号序列。数字表示方式与特定的SACII码相关,而符号表示适用于任何编码方式,其可读性强
-
-
程序清单3.7
- 该程序使用振铃字符(\a)来提醒注意,使用退格字符(\b)来使光标向左退一格
-
程序示例:
//使用转义序列 #include <iostream> using namespace std; int main() { cout << "\aOperation \"HyperHype\" is now activated!\n"; cout << "Enter your agent code:________\b\b\b\b\b\b\b\b"; long code; cin >> code; cin.get(); cout << "\aYou entered " << code << "...\n"; cout << "\aCode verified! Proceed with pian 23:\n"; cin.get(); return 0; }
程序输出:
Operation “HyperHype” is now activated!
Enter your agent code:1234567_
You entered 1234567…
Code verified! Proceed with pian 23:
-
通用字符名
- C++实现支持一个基本的源字符集,即可用来编写源代码的字符集;还有一个基本的执行字符集,它包括在程序执行期间可处理的字符
-
C++有一种表示这种特殊字符的机制,他独立于任何特定的键盘,使用的是通用字符名;例如:
int k\u00F6repr; cout << "Let them eat g\u00E2teau.\n";
- 这些表示的是字符的ISO 10646码点(由Unicode提供)
-
signed char 和 unsigned char
- 与int不同的是,char在默认的情况下既不是没有符号,也不是有符号,是否有符号由C++实现决定
- unsigned char的表示范围为0~255,而signed char 的表示范围为-128~127
-
wcha_t
- wcha_t(宽字符类型)
- 可以表示扩展字符集
- 它是一种整数类型
- 它有足够的空间
- 可以表示系统显使用的最大扩展字符集
-
cin 和 cout 将输入和输出看做是char流,因此不适用于用来处理wcha_t类型;但头文件iostream最新版本提供了作用相似的工具:
- win 和 wcout ——可用于处理wcha_t流
-
可以通过加上前缀L来指示宽字符常量和宽字符串,例如:
wchar_t bob = L'p'; wcout << L"tall" << endl;
- 上述代码将字母p的wcha_t版本存储到变量bob中,并显示tall的wcha_t版本
-
C++11新增的类型:char16_t 和 char32_t
-
char16_t
- 无符号,长16位
- 使用前缀(小写)u表示字符常量和字符串常量,如:u‘C’ 和 u“be good”
-
char32_t
- 无符号,长32位
- 使用前缀(大写)U表示字符常量和字符串常量,如:U‘C’ 和 U“be good”
- 与wchat_t一样,char16_t 和 char32_t 也都有底层类型——一种内置的整型
-
-
bool类型
-
布尔变量的值可以是 true 或 false,例如:
bool is_ready = true;
-
字面值true和false都可以通过提升转换为int类型,true被转换为1,而false被转换为0:
int ans = true; int promise = false;
-
任何数字值都可以被隐式转换,即不用显示强制转换为bool值,任何非0值都被转换为true,而0被转换为false:
bool start = -100; boo stop = 0;
-
-