> For the complete documentation index, see [llms.txt](https://langyo-v2.gitbook.io/cppworld/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://langyo-v2.gitbook.io/cppworld/di-yi-tan-xin-de-zheng-cheng/1-1/1-4.md).

# 第四节 · 篮子与瓶子 · 初识类型

我们在日常生活中，经常会遇到为物品归类的问题。

物品归类的方法有很多，最常用的方法之一是以容器为依据分类。例如，我们可以用篮子装各种的固体，或是用瓶子装各种的液体。

在 C++ 中，我们同样有不同的容器可以使用，也同样有不同形态的数据提供给容器承载。

下面，我们就来认识一些最基本的数据形态——**字面量**。

> 0

这是什么？对，是数字 0！

零是一切的开始，不仅仅是数字，世间万物何尝不是从零开始？

让我们试一试将它在屏幕上呈现出来——沿用之前那些尚不明确合成分具体用途的程序，仅仅修改我们已经了解的用于输出信息的 cout 一行：

```cpp
#include <iostream>
int main()
{
  std::cout << 0 << std::endl;
  return 0;
}
```

很好，我们做到让屏幕输出数字了！

在 C++ 中，我们不仅能表达十进制的数字，也能表达八进制与十六进制的数字，他们经常在实战中被使用。

要想表达一个八进制数，仅需让数字前多一个零即可。例如：

```
0777
0167730
```

要想表达一个十六进制数，需要在数字前加 0x 或 0X 的前缀，且数字中的字母部分不区分大小写。例如：

```
0x12CD
0xeef09ac3
```

我们接下来了解一下浮点数。从数学角度来看，其实它就是小数：

```
3.14159
0.618
```

而在计算机科学中，小数在计算机内部可以被表达为浮点数与定点数。它们都可用于表达小数，但其具体实现方式有点区别：定点数的小数点位置是固定的，无论是整数部分还是小数部分，它们都只能表达固定的范围；浮点数的小数点则可以任意“浮动”，在小数点所能及的范围下，你可以用浮点数的模式表达很大与很小的数字。

要想了解浮点数的工作原理，我们需要先复习数学上的科学记数法。

> 2.1936 x 10^4 = 21936 1.7203 x 10^-6 = 0.0000017203 3.8500 x 10^10 = 38500000000

科学记数法给予了我们一种手段，将一个很大或很小的数字变为一组相对较短的乘法算式，不仅少写了大量的“0”，而且也便于我们一眼就能看出这个数字的规模。

浮点数其实就是这么做的——它将原本的小数拆为三部分：符号位、底数与指数。符号位用于表达这个小数是正数还是负数；底数相当于上面例子中左侧的数字，表达范围必须在 1 到 10 之间(包含 1)；指数则相当于上面例子中 10 的次幂。

由此，C++ 还提供了另一些表达方式——以科学记数法表达小数，也可以是省略了整数或小数部分的小数：

```
3.14159e0 // 3.14159
3E1 // 30
618E-3 // 0.618
123. // 123
.001 // 0.001
```

其中，E 与 e 是用于表达科学记数法的标识符，其左侧是底数，右侧是以底数所用进制为底的指数(例如，左侧为 10 十进制，右侧就以 10 为底)。

刚刚的浮点数中，出现了符号位的身影，并且我们知道它用于表达这个数是正数还是负数。 是的，不论是整数还是浮点数，它们都可以表达负数——只要在数字的开头加一个减号就可以了：

```
-233
-3.1415926
```

看起来与数学中的相差无几，不过还是有所差别——在数学中，减号(负号)与数字一整体直接被看作负数；而在 C++ 语言中，这却相当于先声明一个正整数，然后对其取负。

如果你尝试直接写一个很大很大的整数，编译器会报错：

```cpp
cout << 12345678987654321 << endl;
```

怎么办呢？很简单，在数字末尾加个`L`(或`l`)即可：

```cpp
cout << 12345678987654321L << endl;
```

很显然，C++ 的整数也是有表达范围的。而数字末尾加的`L`，则意味着我们扩大了数字的表达范围。

我们将在后续的章节中，介绍由具体的不同类型引申而来的不同大小限定的数字。

还记得在我们刚刚开始学习时所写的第一道程序么？

```cpp
cout << "Hi, C++ World!" << endl;
```

其中，`"Hi, C++ World!"`中被双引号括起来的内容是可以任意变动的。例如：

```cpp
"Hello, Steve! Where's Chino?"
"You have said JoJo, right?"
```

像这样以双引号包裹的内容称作**字符串**，字符串由一系列字符组成。

当然，字符串的内容也可以含有其它自然语言的文字，不一定非得是英语：

```cpp
"衬衫的价格是 9 镑 15 便士，所以你选择——C。"
```

编译后，可能会由于编译时与运行时的字符集不匹配，输出含有除数字与字母等在 ASCII 字符集之外的文字时很可能会出现乱码。这并没有什么很好的解决方案，因为不同用户所使用的设备可用的字符集很可能是不同的，这也就造成了输出文字的不通用。

不过，我们仍然可以尽可能规避这些问题。

要想在你的机器上正确显示中文，一种妥当的办法是使用**宽字符**字符串——在字符串开头加一个`L`即可：

```cpp
L"衬衫的价格是 9 镑 15 便士，所以你选择——C。"
```

如果希望字符串的内容也可被其它机器使用，另一种可选的办法是让它以 Unicode 字符集保存——开头加`u8`(8 位)、`u`(16 位)或`U`(32 位)均可：

```cpp
u"衬衫的价格是 9 镑 15 便士，所以你选择——C。"
```

Unicode 又称作万国码，它涵盖了全球绝大部分民族的文字，并且也包含了大量的特殊符号。以它来作为字符串的字符集，可以使所有支持 Unicode 的机器可以做到正确显示此类文字。放心，现代的操作系统没有不支持这个字符集的。

前面有提到过，字符串实际上就是由一批字符连起来的整体。

那么，字符又是怎么表示的呢？

很简单，以单引号包裹一个字符即可。注意只能写数字与英文字母等在 ASCII 字符集内的字符：

```cpp
'a'
'1'
```

同样地，它可以像字符串那样；使用`L`、`u`、`U`前缀改变使用的字符集，不过一般情况下我们用不到。

并且字符也可以直接交给`cout`输出：

```cpp
cout << 'N' << endl;
```

## 习题

* 尝试自己写点什么要输出的内容，以`cout`将内容写在屏幕上。
* 尝试以`cout`在屏幕上输出一个浮点数，并调整数字的大小，找一找有什么规律。
