You Know Nothing
  • 主页
  • 分类
  • 标签
  • 归档

C++ Primer 第二章 变量和基本类型

  • 2.1 类型
  • 2.2 如何选择类型
  • 2.3 类型转换
  • 2.4 字面值常量
  • 2.5 指定字面值的类型
  • 2.6 列表初始化
  • 2.7 默认初始化
  • 2.8 分离式编译
  • 2.9 声明
  • 2.10 C++ 标识符
  • 2.11 作用域操作符 ::
  • 2.12 复合类型
    • 2.12.1 引用
    • 2.12.2 指针
  • 2.13 理解复合类型的声明
  • 2.14 const 限定符
  • 2.15 指针和 const
    • 2.15.1 指向常量的指针
    • 2.15.2 const 指针
    • 2.15.3 顶层和底层 const
    • 2.15.4 constexpr 和常量表达式
  • 2.16 处理类型
    • 2.16.1 类型别名
    • 2.16.2 auto 类型说明符
    • 2.16.3 decltype 类型指示符
  • 2.17 自定义数据结构:结构体和类
  • 2.18 头文件保护符

2.1 类型

下表列出了 C++ 标准规定的数据类型尺寸的最小值,同时允许编译器赋予这些类型更大的尺寸

类型 含义 最小尺寸
bool 布尔类型 未定义
char 字符 8位
wchar_t 宽字符 16位
char16_t Unicode 字符 16位
char32_t Unicode 字符 32位
short 短整型 16位
int 整型 16位
long 长整型 32位
long long 长整型 64位
float 单精度浮点数 6位有效数字
double 双精度浮点数 10位有效数字
long double 扩展精度浮点数 10位有效数字

一个char的空间应确保可以存放机器基本字符集中任意字符对应的数字值。也就是说,一个char的大小和一个机器字节一样。

wchar_t类型用于确保可以存放机器最大扩展字符集中的任意一个字符。

C++ 语言规定,一个int至少和一个short一样大,一个long至少和一个int一样大,一个long long至少和一个long一样大。

可寻址的最小内存块成称为“字节(byte)”,存储的基本单元称为“字(word)”,它通常有几个字节组成。

在 C++ 语言中,一个字节至少能容纳机器基本字符串中的字符。大多数机器的字节由8比特构成,字则由32或64比特构成,也就是4字节或8字节。

C++ 标准指定了一个浮点数有效位数的最小值,然而大多数编译器都实现了更高的精度。通常,float以1个字(32比特)来表示,double以2个字(64位)来表示,long double以3或4个字(96或128比特)来表示。一般来说,float和double分别有7和16个有效位;类型long double则常常被用于有特殊浮点要求的硬件,它的具体实现不同,精度也各不相同。

类型int、short、long和long long都是带符号的,通过在这些类型名前添加unsigned就可以得到无符号类型。

char、signed char和unsigned char,char是否等于signed char由编译器决定。

C++ 标准并没有规定带符号类型应如何表示,但是约定了在表示范围内正值和负值的量应该平衡。因此,8比特的signed char理论上可以表示-127至127区间内的值,大多数现代计算机将实际的表示范围定为-128至127。

2.2 如何选择类型

明知数值不可能为负数,选用无符号类型。

如果数值超过了int的表示范围,选用long long,因为long一般和int有一样的尺寸。

算术表达式中不要使用bool或char。

执行浮点数运算选用double。因为float通常精度不够而且计算代价相差无几。long double提供的精度一般情况下是没有必要的而且计算代价大。

2.3 类型转换

非布尔 -> 布尔:0 -> false,其他 -> ture。

布尔 -> 非布尔:false-> 0,ture -> 1。

浮点 -> 整型:仅保留小数点前。

整型 -> 浮点:小数部分记为0,如果该整数所占的空间超过浮点类型的容量,精度可能损失。

当我们赋给无符号类型一个超过它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。

当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的。此时,程序可能继续工作、可能崩溃,也可能生成垃圾数据。

当一个算术表达式中既有无符号数又有int值时,那个int会转换成无符号数。把int转换成无符号数的过程和把int赋值给无符号变量一样。

当从一个无符号数中减去一个值时,我们必须确保结果不是负值,否则实际结果会是取模后的值。

2.4 字面值常量

整型和浮点型字面值。

字符和字符串字面值:

  • ‘a’ 和“a”,字符串字面值最后补’\0’
  • 如果两个字符串字面值位置紧邻且仅由空格、缩进和换行分隔,则它们是一个整体

布尔字面值:true、false。

指针字面值:nullptr。

2.5 指定字面值的类型

字符和字符串字面值

前缀 类型
u char16_t
U char32_t
L wchar_t
u8 char

整型字面值

后缀 最小匹配类型
u 或 U unsigned
l 或 L long
ll 或 LL long long

浮点型字面值

后缀 类型
f 或 F float
l 或 L long double

2.6 列表初始化

int units_sold{0}

列表初始化的重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错。

2.7 默认初始化

内置类型变量

  • 定义于任何函数之外,初始化为0
  • 定义于函数体内的局部静态变量,初始化为0
  • 定义于函数体内的非局部静态变量,不被初始化,试图拷贝或以其他方式访问此类值将引发错误

每个类各自决定其初始化对象的方式。

2.8 分离式编译

将程序分割为若干个文件,每个文件可被独立编译

2.9 声明

extern int i;

extern语句如果包含初始值就不再是声明,而变成定义了:extern int i = 0;在函数体内部,试图初始化一个由extern关键字标记的变量将引发错误。

静态类型语言:在编译阶段执行类型检查

2.10 C++ 标识符

字母、数字、下划线,必须以字母或下划线开头,长度无限制,大小写敏感。

C++ 为标准库保留了一些名字

  • 自定义标识符中不能连续出现两个下划线
  • 不能以下划线紧接大写字母开头
  • 定义在函数体外的函数不能以下划线开头

2.11 作用域操作符 ::

若左侧为空,则指代全局作用域

2.12 复合类型

2.12.1 引用

int &b = a;b指向a。

引用必须初始化。

引用本身不是一个对象,不能定义引用的引用。

引用必须绑定到对象上,不能绑定到字面值或者某个表达式的计算结果上。

除了两种例外,所有引用的类型都要和它所绑定的对象严格匹配:

  • 初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可
  • 允许将基类的引用绑定到派生类上

2.12.2 指针

int *b = &a;。

指针是一个对象。

在块作用域内定义的指针如果未初始化,将拥有一个不确定的值。

除了两种例外,所有指针的类型都要和它所指向的对象严格匹配:

  • 允许一个指向常量的指针指向一个非常量对象
  • 允许将基类的指针绑定到派生类上

试图拷贝或以其他方式访问无效指针的值将引起错误,编译器不负责检查此类错误。

任何非零的指针对应的条件值都是true。

合法指针可以比较大小:== 或 !=。

void *是一个特殊的指针类型,可用于存放任意对象的地址,只支持有限的操作:

  • 拿它和别的指针比较
  • 作为函数的输入或输出
  • 赋给另外一个void *指针

2.13 理解复合类型的声明

变量的定义包括一个基本数据类型和一组声明符。

一条定义语句可能定义出不同类型的变量:int i = 1024, *p = &i, &r =i;。

面对一条比较复杂的指针或者引用的声明语句时,从右往左阅读有助于弄清楚它的真实含义,例如:int \*&r;首先 r 是一个引用,其次 r 是一个指针的引用,再次 r 是一个指向整型指针的引用。

2.14 const 限定符

因为const对象一旦创建就无法改变其值,所以必须初始化。

当用一个对象去初始化另外一个对象,它们是不是const都无关紧要,常量的特性仅仅在执行改变其值的操作时才会发挥作用。

默认情况下,const对象仅在文件内有效。

如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。

const的引用,常量引用的初始化:初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。尤其,允许为一个常量引用绑定非常量的对象、字面值甚至是一个表达式。实际上是通过绑定到一个临时量对象上实现的。

对const的引用可能引用一个并非const的对象,常量引用仅对引用可参与的操作做了限制,对于引用的对象本身是不是常量未做限制。

2.15 指针和 const

2.15.1 指向常量的指针

允许一个指向常量的指针指向一个非常量对象。

仅对指向常量的指针可参与的操作做了限制,对于指向的对象本身是不是常量未做限制。

2.15.2 const 指针

指针是对象,可以把指针本身定为常量。

常量指针必须初始化,一经初始化就不能再改变。

把*放在const关键字之前说明指针是一个常量。

2.15.3 顶层和底层 const

顶层const:指针本身是个常量。

底层const:指针所值的对象是一个常量。

更一般的,顶层const可以表示任意的对象是常量,这一点对任意数据类型都适用。底层const则与指针和引用等复合类型的基本类型部分有关。

执行对象的拷贝操作时,顶层const不受影响;拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。一般来说,非常量可以转换成常量,反之不行。

2.15.4 constexpr 和常量表达式

常量表达式:值不会改变并且在编译过程就能得到计算结果的表达式。

constexpr变量:由编译器来验证变量的值是否是一个常量表达式,声明为constexpr的变量一定是一个常量,并且必须用常量表达式初始化。

字面值类型:算术类型、引用、指针、字面值常量类、枚举。

声明constexpr用到的类型为字面值类型。

一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象:

  • 函数体内定义的变量一般并非存放在固定地址中,constexpr指针不能指向这样的变量(局部静态对象除外)
  • 定义于所有函数体之外的对象地址固定不变,能用来初始化constexpr指针

在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关。

constexpr把它所定义的对象置为顶层const。

2.16 处理类型

2.16.1 类型别名

typedef double wages;

using SI = Sales_item;

2.16.2 auto 类型说明符

让编译器自己去分析表达式所属的类型。

auto也能在一条语句中声明多个变量。因为一条声明语句只能有一个基本数据类型,所以该语句中所有变量的基本数据类型都必须一样。

当引用被用作初始化auto变量时,编译器以引用所引用对象的类型作为auto的类型。

auto一般会忽略顶层const,同时底层const会保留下来。

如果希望推断出的auto类型是一个顶层const,需要明确指出。

auto引用auto &b = a;初始值 a 的顶层const会保留。

2.16.3 decltype 类型指示符

选择并返回操作数的数据类型,编译器分析表达式得到它的类型,却不实际计算表达式的值,编译器并不实际调用f。

如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内),需要指出的是,引用从来都作为其所指对象的同义词出现,只有在decltype处是一个例外。

如果decltype使用的表达式不是一个变量,则decltype返回该表达式的结果对应的类型:

  • 因为 r 是一个引用,decltype(r)的结果是引用类型,如果想让结果类型是 r 所指的类型,可以把 r 作为表达式的一部分,显然这个表达式的结果是一个具体的值而非一个引用
  • 如果表达式的内容是解引用操作,则decltype将得到引用类型

如果decltype使用的表达式是一个变量:

  • 不加括号,得到该变量的类型
  • 加括号,得到引用类型

2.17 自定义数据结构:结构体和类

记得定义末尾的分号。可以类内初始化。

2.18 头文件保护符

头文件保护符依赖于预处理变量。

预处理变量由两个状态:已定义和未定义。

#define指令把一个名字设定为预处理变量。

#ifdef当且仅当变量已定义时为真。

#ifndef当且仅当变量未定义时为真。

一旦检查结果为真,则执行后续操作直到遇到#endif指令为止


RELATED

  • C++ 中的类型转换
  • C++ Primer 第十七章 标准库特殊设施
  • C++ Primer 第十六章 模板与泛型编程
  • C++ Primer 第十五章 面向对象程序设计
  • C++ Primer 第十四章 重载运算与类型转换

OLDER

  • 利用 Mac stat 添加文件创建时间、最后修改时间
  • C++ Primer 第一章 开始
  • Python 教程
  • HTML 入门
  • X3DOM 图像和视频纹理

NEWER

  • C++ Primer 第三章 字符串、向量和数组
  • C++ Primer 第四章 表达式
  • CSS 入门
  • 剑指 offer (1)
  • Linux 中的扩展和引用

发布日期

2018-10-06 22:02:54

最后更新

2018-10-07 10:48:38

分类

C++

标签

  • C++ 18
  • Powered by Pelican. Theme: Elegant by Talha Mansoor