C++primer 第2章 变量和基本类型

[总结:]
  • 类型是C++程序设计的基础
  • 每种类型都定义了其存储空间要求和可以在该类型的所有对象上执行的操作.C++提供了一组基本内置类型,如int,char等.这些类型与它们在机器硬件上的表示方式密切相关.
  • 类型可以分为const和非const; const对象必须要初始化,且其值不能被修改.另外,我们还可以定义复合类型, 如引用. 引用为对象提供了另一个名字.复合类型是用其他类型定义的类.
  • C++语言支持通过定义类来自定义类型. 标准库使用类设施来提供一组高级的抽象概念, 如IO和string类型.
  • C++是一宗静态类型语言:变量和函数在使用前必须声明。变量可以声明多次但是只能定义一次。定义变量时候就进行初始化几乎总是个好主意
1. 基本内置类型

类 型 含 义 最小存储空间
bool 布尔型 ——
char 字符型 8位
wchar_t 宽字符型 16位
short 短整型 16位
int 整型 16位
long 长整型 32位
float 单精度浮点型 6位有效数字
double 双精度浮点型 10位有效数字
long doble 扩展精度浮点型 10位有效数字

  • 因为位数不同,这些类型所能表示的最大(最小)值也因机器的不同而有所不同。
  • 让存储具有结构的最基本方法是用块(chunk)处理存储。通常将8位的块作为一个字节4个字节(32位)作为一个“字”(word)
  • 带符号signed和无符号unsigned类型
    • unsigned int 类型可以简化写成unsigned,也就是说,unsigned后面不加其他类型说明符就意味着是:unsigned int。
    • 符号位为1,值就为负数;符号位为0,值就为0或正数。
    • 对于unsigned类型来说,负数总是超过其取值范围。unsigned类型的对象可能永远不会保存负数。但在C++中,把负数赋值给unsigned对象是完全合法的,其结果是该负数对该类型的取值个数求模后的值。
           例如:把-1赋值给8位的unsigned char,那么结果是255
                    由于-1的补码是11111111(原码绝对值取反加一)结果就是255的二进制编码。
           
  • 浮点型,类型float,double和long double分别表示单精度浮点数,双精度浮点数和扩展精度浮点数。
    • 一般float类型用一个字(32位)来表示,double类型用两个字(64位)来表示,long double 类型用三个或四个字(96位或128位)来表示。
    • 对于实际程序来说float类型的精度通常是不够的——float只能保证6位有效数字,而double型至少可以保证10位有效数字,能满足大多数计算的需要。
2. 字面值常量
  • 42这样的值在程序中就被当做字面值常量。字面值是指只能用它的值来称呼它,常量是指它的值不能修改。只有内置类型存在字面量,没有类类型的字面量,因此也没有任何标准库类型的字面量。
  • 整型字面值规则
    • 20         //十进制
    • 024       //八进制
    • 0x14     //十六进制
    • 字面值整数常量的默认类型是int或long类型。其精度类型决定于字面值——其值适合int就是int类型,适合long就是long类型。也可以通过增加后缀,强制将字面值整数常量转换为long,unsigned或unsigned long类型。
    • 通过在数值后面加L或者l制定常量为long类型(推荐使用大写L,因为小写l容易和1混淆)
    • 类似,可以通过在数值后面加U或u定义unsigned类型。同时加L和U就能够得到unsigned long类型的字面值常量(后缀之间没有空格)。
        例子:128U   /*unsigned*/       1024UL   /*unsigned long*/
                 1L       /*long*/              8Lu       /*unsigned long*/
    • 没有short类型的字面值常量。
  • 浮点字面值规则:
    • 默认的浮点字面值常量位double类型。
    • 在数值后面加上F或者f表示单精度;加上L或l表示扩展精度。
    • 例子:3.14159F      12.345L     1.2345E1L
  • 布尔字面值和字符字面值:
    • 可打印的字符型字面值通常用一对单引号来定义:
            'a'    '2'   ','    ' ' //blank
    • 在字符字面值的前面加L就可以得到wchar_t类型的宽字符字面值。
    • "wchar_t是C/C++的字符数据类型,是一种扩展的字符存储方式,wchar_t类型主要用在国际化程序的实现中,但它不等同于unicode编码。unicode编码的字符一般以wchar_t类型存储。char是8位字符类型,最多只能包含256种字符,许多外文字符集所含的字符数目超过256个,char型无法表示。
      wchar_t数据类型一般为16位或32位,但不同的C或C++库有不同的规定,如GNU Libc规定wchar_t为32位,总之,wchar_t所能表示的字符数远超char型。
      标准C++中的wprintf()函数以及iostream类库中的类和对象能提供wchar_t宽字符类型的相关操作。"
  • 非打印字符的转义序列 :
换行符 \n 水平制表符 \t
纵向制表符 \v 退格符 \b
回车符 \r 进纸符 \f
报警(响铃)符 \a 反斜线 \\
疑问号 \? 单引号 \'
双引号 \"    
    • 我们可以将任何的字符表示为一下形式的通用转义字符:
      • \ooo   这里的ooo表示3个八进制的数字,这三个数字表示字符的数字值。                    
      • \7  \12  \40 \0   \062 \115  
        响铃符 换行符 空格符 空字符 '2' 'M'
         
      • 同样也可以用十六进制转义字符来定义字符:\xddd   由反斜线,一个x和一个或多个十六进制数字组成。
  • 字符串字面值:
    • 字符串字面值常量用双引号括起来的0个或多个字符表示。
    • C++兼容C,所有字符串字面值都由编译器自动在末尾添加一个空字符。
    • 同样也存在宽字符串字面值,一样在前面加L。如:L"a wide string literal".
    • 宽字符串字面量是一串常量宽字符,同样以一个宽空字符结束。
      1. std::cou\
      2. t<<"Hi"<<st\
      3. d::endl;
    • 等价于:
      1. std::cout<<"Hi"<<std::endl;
    • 利用这个特性可以编写长字符串字面值:
      1. std::cout<<"a multi-line\
      2. string literal\
      3. using a backslash"
      4. <<std::endl;
3. 变量
  • 左值 (lvalue,发音为ell-vallue)左值可以出现在赋值语句的左边或右边
  • 右值 (rvalue,发音为are-valle)右值只能出现在赋值的右边
    • 变量时左值,因此可以出现在赋值语句的左边
    • 数字字面值是右值,因此不能被赋值。
  • 变量命名

  • 变量命名习惯:
  • 变量名一般用小写字母。
  • 定义
    • 区别初始化和赋值:初始化指创建变量并给它赋初始值,而赋值则是擦除对象的当前值并用新值代替;
    • 可以通过一个计数器和一个字符初始化string对象。这样创建的对象包含重复多次的指定字符,重复次数由计数器指定:
            std::string all_nines(10,'9');    //all_nines="9999999999"
            初始化all_nines的唯一方法就是直接初始化。
  • 初始化规则
    • 系统会根据变量的类型和变量定义的位置自动帮我们初始化。
    • 内置类型变量的初始化:
      • 内置类型变量是否自动初始化取决于变量定义的位置。在函数体外部定义的变量都初始化成0
      • 函数体内定义的内置类型变量不进行自动初始化。
    • 类类型变量的初始化:
      • 类通过定义一个或多个构造函数来控制类对象的初始化。
      • 如果定义某个类的变量时没有提供初始化式,那么就会使用默认构造函数,无论变量在哪里定义,默认构造函数都会被使用。
      • std::string empty;      // empty is the empty string; empty=" "
  • 声明和定义
    • 任何在多个文件中使用的变量都需要有与定义分离的声明。在这种情况下,一个文件含有变量的定义,使用该变量的其他文件则包含该变量的声明(而不是定义)。
4. const限定符
  • 定义const对象
    • const限定符将一个对象转换成一个常量。
    • const int bufSize=512;       // input buffer size
    • 定义bufSize为常量并初始化为512,任何修改bufSize的尝试都会导致编译失败;
    • 因为常量在定义后就不能被修改了,所以在定义的时候就必须进行初始化。
  • const对象默认为文件的局部变量
    • 与其他变量不同,在全局作用域中声明的const变量是定义该对象的文件的局部变量。就是说,此变量只存在于那个文件中,不能被其他文件访问。
    • 但是可以通过制定const变量为extern,就可以在整个程序中访问const对象;
    • 非const变量默认为extern,要使const变量能够在其他的文件中访问,必须显式地制定它为extern。
5.引用
引用就是对象的另一个名字,引用主要用做函数的形参。
  • 引用是一种复合类型,通过在变量名前添加“&”符号来定义,
  • 引用必须使用与该类型的对象初始化:
    • int iva1=1024;
    • int &refVa1=ival;             // ok,  refVa1 refers to iva1
    • int &refVal12;                 // error,  a reference must be initialized
    • int &refVa13=10;            // error,  initializer must be an object
  • 初始化是指明引用指向哪个对象的唯一方法;
  • 引用只是一个对象的另一个名字;
  • 当引用初始化后,只要该引用存在,它就保持绑定到初始化时指向的对象,不能将引用绑定到另一个对象。
  • const引用
    • const引用是指向const对象的引用。可以读取但不能修改。
6.typedef名字
    • typedef可以用来定义类型的同义词;
    • typedef定义以关键字typedef开头,后面是数据类型和标示符。
      • typedef double wages;// wages is a synonym for double
      • wages hourly=12.45;    // double hourly=12.45
7.枚举
    • 我们经常需要为某些属性定义一组可以可选择的值。枚举不仅提供了一种方法定义了整数常量集,而且还把它们聚集成组;
    • 定义和初始化:
      • enum point{point1,point2,point3};                // point1=0;  point2=1; point3=2;
      • enum point{point1=1,point2,point3};                // point1=1;  point2=2; point3=3;
      • enum point{point1=1,point2,point3=5,point4,point5};                 // point1=1;  point2=2; point3=5; point4=6; point5=7;
    • 不能改变枚举成员的值。枚举成员本身就是一个常量表达式,所以也可用于需要常量表达式的任何地方。
8.类类型
    • 每个类都定义了一个接口和一个实现。
    • 定义类时,通常先定义该类的接口,即该类所提供的操作。通过这些操作,可以决定该类完成其功能所需要的数据,以及是否需要定义一些函数来支持这个类的实现。
    • 定义Sales_item类
      • class Sales_item{
      •     public:
      •           //operations onSales_item objects will go here
      •     private:
      •          std::string isbn;
      •          unsigned units_sold;
      •          double revenue;
      • };
        • 最后的分号不能掉!
    • 类的数据成员(橙色部分)
      • 当定义数据成员时,只能指定该数据成员的名字和类型。
      • 不能在类定义里定义数据成员的时候  初始化数据成员,而是通过构造函数的特殊成员函数控制初始化。
    • 访问标号
      • public部分定义的成员在程序的任何部分都可以访问。
      • private部分定义的成员,不是类的组成部分的代码不能访问。
    • 使用struct关键字定义类类型。(struct是从C语言中继承过来的)
      • 如果使用class关键字来定义类,那么定义在第一个访问标号前的任何成员都隐式指定为private;
      • 如果使用struct关键字来定义类,那么这些成员都是public
      • 使用class还是struct关键字来定义类,仅仅影响默认的初始访问级别。
9.编写自己的头文件
  • 头文件的正确使用能够带来2个好处:保证所有文件使用给定尸体的同一声明;当声明需要修改时,只有头文件需要更新;
  • 头文件用于声明而不是用于定义;
  • 一些const对象定义在头文件中
  • 预处理器
    • #include设施是C++预处理器的一部分,预处理器处理程序的源代码,在编译器之前运行。
    • #include指示只接受一个参数:头文件名。
    • 为了避免名字冲突,预处理器变量用全大写字母表示
      • 预处理器变量有两种状态:已定义和未定义;
      • #define 指示接受一个名字并定义该名字为预处理器变量;  #ifndef 指示检测指示的预处理器变量是否未定义,如果预处理器变量未定义,那么跟在后面的所有指示都被处理,直到出现#endif ;
      • #ifndef SALESITEM_H
      • #define SALESITEM_H
      • //使用这些设施来预防多次包含同一头文件
      • #endif
  • #include指示接受以下两种形式:
    • #include <standard_header>
    • #include "my_file.h"
    • 如果头文件名包括在尖括号<>里,那么认为该头文件是标准头文件。编译器将会在预定义的位置集查找该头文件。
    • 如果头文件名包括在一对引号中,那么认为它是非系统文件,查找通常开始于源文件的所在路径。
posted @ 2013-05-22 21:18  SEA Liu  阅读(500)  评论(0编辑  收藏  举报