《C++Primer》第二章-变量和基本类型-学习笔记(1)

《C++Primer》第二章-变量和基本类型-学习笔记(1)

日志:
1,2020-02-25 笔者提交文章的初版V1.0

作者按:
最近在学习C++ primer,初步打算把所学的记录下来。之前学的知识有些淡忘了,看来得经常复习,得三省吾身,传不习乎才能牢固啊。
Nobody trips over mountains. It is the small pebble that causes you to stumble. Pass all the pebbles in your path and you will find you have crossed the mountain.

传送门/推广
《C++Primer》第二章-变量和基本类型-学习笔记(2)

摘要

类型是所有程序的基础。类型可以告诉我们数据代表什么样的意思以及我们可以对数据执行哪些操作。
类型的概念在C ++中非常重要。每个变量,函数参数和函数返回值都必须具有类型才能进行编译。同样,编译器在评估每个表达式(包括字面值)之前会隐式[5]为其指定类型。
C++ 中对类型的支持是非常广泛的:语言本身定义了一组基本类型和修改已有类型的方法,还提供了一组特征用于自定义类型。

  • C++定义的基本类型有:字符型,整型,浮点型等。
  • 同时C++还提供了可用于自定义数据类型的机制,举个例子,标准库正是利用这些机制定义了许多更复杂的类型,例如可变长字符串类型string。
  • 此外我们还能够修改已有的类型形成复合类型(compound type)

主体

一种语言,首先有基本类型,其实就是数据在内存的布局,方便表示不同种类的数据,例如整型和浮点是一定要有的,因为 cpu 的规范。再组合得到数组,函数类型等,再发展出代数类型,然后包装成接口、类、泛型等高级概念。
基本类型在编译器里规定。至于标准库中定义的类型,通常是某种组合的封装,例如标准库的容器类等。c_str 实际是字符数组,而 std::string 则是进一步的封装,来实现更多的接口方便用户。
有个区别的概念是类型系统。类型系统本身放在编译器(或解释器)里比较好,在编译的同时做类型检查,而在库里,就是运行期检查了。类型系统,描述对类型的判断、推导,例如推导 AST 节点的类型,判断合法或非法,又如类型之间可以如何上下转化。
再比如高阶的多态类型(泛型)或者依赖类型,一般把类型的定义(名称 + 表达式)也放在库里。但是类型系统,即根据定义(表达式)产生实际类型的推导规则(即算法),是在编译器(或解释器)中。
C ++是一种强类型的语言,它也是静态类型的[6]。每个对象都有一个类型,并且该类型永不更改(不要与静态数据对象混淆)。在代码中声明变量时,必须要么明确指定其类型,要么使用auto关键字指示编译器从初始化程序中推断类型。在代码中声明函数时,必须指定每个参数的类型及其返回值;如果函数未返回任何值,则必须指定void。唯一的例外是使用函数模板时,该模板允许使用任意类型的参数。

C++首次声明变量后,以后将无法更改其类型。但是,可以将变量的值或函数的返回值复制到其他类型的变量中。这种操作称为类型转换,有时是必需的,但它们也是数据丢失或不正确的潜在原因。

基本(内置)类型

C++包括许多基本类型(fundamental type),也称为内置类型(built-in type)。这包括数值类型(numeric types),例如int,double,long,bool,以及分别用于ASCII和UNICODE字符的char和wchar_t类型。大多数基本类型(bool,double,wchar_t以及它们的相关类型除外)都具有无符号版本,这些版本会修改变量可以存储的值的范围。例如,一个int存储32位带符号整数时,其值范围可以表示-2,147,483,648到2,147,483,647。一个无符号整数(也存储为32位)可以存储从0到4,294,967,295的值。在每种情况下,可能值的总数相同,只有范围不同。

来自英文百科的关于内置类型的介绍
built-in type
A data type provided by a programming language as a basic building block, such as integer, character or Boolean, but in some languages
also list, hash table or first class function.[2]

上面的英文意思是说内置类型是编程语言提供的,用来作为基础构建模块的数据类型,比如整型,字符型或布尔型,但是在有的语言中也可以是list类型,哈希表,first class function等。

基本类型由编译器识别,该编译器具有内置规则( built-in rules),这些规则控制可以对它们执行的操作以及如何将它们转换为其他基本类型。

关于基本内置类型,C++ 定义了一套包括算术类型(arithmetic type)空类型(void)在内的基本数据类型.

算数类型

算术类型分为两类:

  • 整型(integral type)
    • 表示整数,字符和布尔值(int,char,bool)的算数类型合称为整型。
  • 浮点型(floating-point type )
    • 包括float,double,long double。
    • 浮点型简单来说表示带有小数的数据,小数点可以在相应的二进制的不同位置浮动。
    • 注意,浮点型都是有符号的。

算术类型的尺寸(该类型数据所占的比特数)在不同机器上有所差别,C++ 标准规定了尺寸的最小值,同时允许编译器赋予这些类型更大的尺寸。某一类型所占的比特数不同,它所能表示的数据范围也不同。
除字符和布尔类型之外,其他整型用于表示(可能)不同尺寸的整数。
C++标准指定了一个浮点数有效位数的最小值,然而大多数编译器都实现了更高的精度。表1列出了内置算术类型及其对应的最小存储空间。

类型 含义 最小存储空间
bool 布尔型 -
char 字符型 8位
short 短字符型 16位
wchar_t 宽字符型 16位
int 整型 16位
long 长整型 32位
float 长整型 6位有效数字
double 双精度浮点型 10位有效数字
long double 扩展精度浮点型 10位有效数字
表1.C++内置算术类型表
整型

C++中表示整数(short,int, ,long),字符(char ,wchar_t)和布尔值(bool)的算数类型合称为整型。
字符类型有两种:char 和 wchar_t。char类型保证了有足够的空间,能够存储机器基本字符集中任何字符相应的数值,因此,char 类型通常是单个机器字节(byte)。char类型用于表示ASCII字符。wchar_t 类型用于扩展字符集,比如汉字和日语,这些字符集中的一些字符不能用单个 char 表示。wchar_t类型用于表示UNICODE字符。
short、int 和 long 类型都表示整型值,存储空间的大小不同。一般, short类型为半个机器字长,int 类型为一个机器字长,而 long 类型为一个或两个机器字长(在 32 位机器中 int 类型和 long 类型通常字长是相同的)。

除了 bool 类型外,整型可以是带符号的(signed)也可以是无符号的(unsigned)
整型 int、short 和 long 都默认为带符号型。要获得无符号型则必须指定该类型为 unsigned,比如 unsigned long。unsigned int 类型可以简写为unsigned
和其他整型不同,char 有三种不同的类型:plain charunsigned charsigned char。虽然 char 有三种不同的类型,但只有两种表示方式。可以使用unsigned char 或 signed char 表示 char 类型。使用哪种 char 表示方式由编译器而定。(plain char就是不加前缀的char ,具体是否有符号,要看编译器是否有选项–signed_chars)

整型的赋值
对象的类型决定对象的取值。对于整型的赋值而言,当把一个超出其取值范围的值赋给一个指定类型的对象时,会产生什么效果呢?答案取决于这种类型是 signed 还是 unsigned 的。

对于 unsigned 类型来说,编译器必须调整越界值使其满足要求。编译器会将该值对 unsigned 类型的可能取值数目求模,然后取所得值。例如,如果试图将 336 存储到 8 位的 unsigned char 中,则实际赋值为 80,因为 80 是 336 对 256 求模后的值。
对于 unsigned 类型来说,负数总是超出其取值范围。unsigned 类型的对象可能永远不会保存负数。有些语言中将负数赋给 unsigned 类型是非法的,但在 C++ 中这是合法的。
当将超过取值范围的值赋给 signed 类型时,由编译器决定实际赋的值。

浮点型

类型 float、 double 和 long double 分别表示单精度浮点数、双精度浮点数和扩展精度浮点数。一般 float 类型用一个字(32 位)来表示,double 类型用两个字(64 位)来表示,long double 类型用三个或四个字(96 或 128 位)来表示。类型的取值范围决定了浮点数所含的有效数字位数。

空类型

void类型没有对应的值,仅仅用在有限的一些情况下,通常用作为无返回值函数的返回类型。
空类型(void)是一种特殊类型; C++中不能声明类型为void的变量,但是可以声明类型为void *(指向void的指针)的变量,这在分配原始(un-typed/未类型化)内存时有时是必需的。
但是,指向void的指针不是类型安全(type-safe)的,通常在现代C ++中强烈建议不要使用它们。在函数声明中,返回值无效意味着函数不返回值;这是void的常见且可接受的用法。尽管C语言要求参数为零的函数在参数列表中声明void,比如function(void),在现代C ++中不鼓励这种做法,应该声明function()。

字符串类型

严格来说,C ++语言没有内置的字符串类型。在C++中字符串类型分为两种,分别是C-style stringstring类库的string
因为char和wchar_t只能存储单个字符,所以要存储字符串的话必须声明这些类型的数组,并将在添加一个终止的空值(例如ASCII 的’\0’)在数组元素的最后一个有效字符之后(也称为C样式字符串,C-style string) 。C-style string需要编写更多代码或使用外部字符串实用程序库函数。
但是在现代C ++中,我们有标准库类型std::string(对于8位char型字符串)或std::wstring(对于16位wchar_t型字符串)。这些C ++标准库容器可被视为本机字符串类型,因为它们是任何兼容C ++构建环境中包含的标准库的一部分。只需使用#include 指令即可在程序中使用这些类型。(如果使用的是MFC或ATL,也可以使用CString类,但它不是C ++标准的一部分。)在现代C ++中,强烈建议不要使用以空字符结尾的字符数组(即前面提到的C样式字符串)。

参考资料

【1】C++ Primer 中文版(第四版·特别版)
【2】built-in type 英文百科
【3】Microsoft Basic Concepts (C++)
【4】Microsoft C++ type system

注解

【5】隐式:编译器完成的转换。显式:用户完成的转换。https://www.cnblogs.com/pityhero233/p/8146585.html
【6】强类型语言:也称为强类型定义语言。是一种总是强制类型定义的语言,要求变量的使用要严格符合定义,所有变量都必须先定义后使用。C++ 是一门静态类型语言,在编译时会作类型检查。
在大多数语言中,对象的类型限制了对象可以执行的操作。如果某种类型不支持某种操作,那么这种类型的对象也就不能执行该操作。在 C++ 中,操作是否合法是在编译时检查的。当编写表达式时,编译器检查表达式中的对象是否按该对象的类型定义的使用方式使用。如果不是的话,那么编译器会提示错误,而不产生可执行文件。随着程序和使用的类型变得越来越复杂,我们将看到静态类型检查能帮助我们更早地发现错误。静态类型检查使得编译器必须能识别程序中的每个实体的类型。因此,程序中使用变量前必须先定义变量的类型。

本文许可证

本文遵循 CC BY-NC-SA 4.0(署名 - 非商业性使用 - 相同方式共享) 协议,转载请注明出处,不得用于商业目的。
CC BY-NC-SA 4.0
下一篇
《C++Primer》第二章-变量和基本类型-学习笔记(2)

发布了52 篇原创文章 · 获赞 72 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/engineerxin/article/details/104515154