登堂入室C++之基础类型

类型

C++的类型分为基础类型和复合类型。

基础类型

基础类型包含以下类型

void

void:表示空,比如表示函数什么都不返回。

nullptr_t

nullptr_t: 也就是空指针字面变量(nullptr)的类型。它的特殊之处在于这个类型本身并不是一个普通指针类型,也不是一个指向成员的指针类型。它的值(nullptr)是一个null pointer constants,可以隐式转换为任何指针或者指向成员的指针类型。

整数类型

  1. bool类型

  2. 字符类型:

窄字符类型有char, signed char, unsigned char。c++20又引入了char8_t

char类型一直以来的问题就是有的平台是有符号数数,有的平台是无符号数。X86 GNU/Linux和Windows使用的是signed char,而PowerPC和ARM处理器一般都是使用unsigned char作为char

char8_t引入指定了使用的是unsigned char,但是它并不是unsigned char的别名,而是一个新的类型。它用来保证一定可以装下utf-8的字符。

宽字符类型有wchar_t,c++11中引入了char16_t, char32_t

需要注意的是char16_t是用来存储UTF-16的字符,它是uint_least16_t的别名。也就是说:1. 它保证是无符号的;2. 至少有16比特,但是不一定,可能有20比特,也可能有32比特。char32_t也是一样的,是uint_least32_t的别名,用来存储UTF-32的字符。

  1. 无符号整数

包括unsigned short int, unsigned int, unsigned long int。从C99(C语言1999标准),头文件stdint.h引入了如下的无符号类型:

  • uint8_t: 精确的8比特无符号数
  • uint16_t: 精确的16比特无符号数
  • uint32_t: 精确的32比特无符号数
  • uint64_t: 精确的64比特无符号数

还有如下fast系列

  • uint_fast8_t:至少8比特的最快的无符号整数类型
  • uint_fast16_t:至少16比特的最快的无符号整数类型
  • uint_fast32_t:至少32比特的最快的无符号整数类型
  • uint_fast64_t:至少64比特的最快的无符号整数类型

以及最小内存系列

  • uint_least8_t:至少8比特的无符号整数类型
  • uint_least16_t:至少16比特的无符号整数类型
  • uint_least32_t:至少32比特的无符号整数类型
  • uint_least64_t:至少64比特的无符号整数类型

个人理解是fast系列偏向速度,least系列偏向内存消耗。比如寄存器至少都是16位的,那么uint_fast8_t选择uint16_t应该就比uint8_t要好。而对于uint_least8_t就刚好相反,它更看中存储大小,选择uint8_t更好。

fast和least系列大家使用不多。日常编程建议使用精确大小的无符号类型,这样确定知道大小。因为c++标准是没有规定具体大小的,只是规定了signed char, unsigned char是至少有8比特;short int, unsigned short int是至少有16比特;int, unsigned int至少有16比特;long int, unsigned long int至少有32比特;long long int, unsigned long long int至少有64比特。所以我们只知道至少多少比特,并不知道具体多少比特,如果我们的程序是需要跨平台的,就可能在不同平台出现不一致的表现。

对于一个二进制序列b_n b_{n-1} b_{n-1} b_{n-3} \cdots b_b b_0,其表达的十进制值为:
v = \sum_{i=0}^n b_i 2^i

比如一个3比特的二进制,我们有

overflow-uint.jpg
  1. 有符号整数

包括short int, int, long int。从C99(C语言1999标准),头文件stdint.h引入了如下的无符号类型:

  • int8_t: 精确的8比特有符号数
  • int16_t: 精确的16比特有符号数
  • int32_t: 精确的32比特有符号数
  • int64_t: 精确的64比特有符号数

还有如下fast系列

  • int_fast8_t:至少8比特的最快的有符号整数类型
  • int_fast16_t:至少16比特的最快的有符号整数类型
  • int_fast32_t:至少32比特的最快的有符号整数类型
  • int_fast64_t:至少64比特的最快的有符号整数类型

以及最小内存系列

  • int_least8_t:至少8比特的有符号整数类型
  • int_least16_t:至少16比特的有符号整数类型
  • int_least32_t:至少32比特的有符号整数类型
  • int_least64_t:至少64比特的有符号整数类型

n比特的有符号整数中我们用最高比特用来表达-2^{n-1},其它比特按照无符号整数进行表达,表达的十进制为
v = -2^{n-1}b_n + \sum_{i=0}^{n-1}b_i2^i

3比特的的表达我们可以表示如下图:

overflow-int-3.jpg

纯粹从2进制比特来看,对于一个有符号整数,-x的表示(x>0)是x的二进制取反加上1。

比如上图中2的二进制为010, -2的二进制110,恰好是010取反得到的101加上1得到。

浮点数类型

浮点类型包括float, double, long double。都是使用IEEE 754标准表达。

IEEE 754表达方式为:

| sign | exponent | fractional |

浮点数的二进制表示分为三个部分

  1. 1位表示符号(记做s):0表示正数,1表示负数;
  2. k位表示指数(记做E):(e_{k−1}e_{k−2}e_{k−3}...e_0)_2
  3. n位表示小数部分(记做M):(m_1m_2m_3...m_n)_2=m_1×2^{−1}+m_2×2^{−2}+⋯+m_n×2^{−n}

浮点数就表示为(−1)^s×M×2^E

对于32位的浮点数,k=8, n=23;对于64位的浮点数,k=11,n=52。

首先根据表示指数的位数我们设置一个偏移量Bias(Bias=2^{k−1}−1)。这个偏移量来干什么呢?k比特的二进制数是一个大于等于0的十进制数,是没有办法表达负数的。而我们其实是需要负数来表示小于1的数的。所以我们设置一个偏移量来干这个事情。

对于浮点的指数部分,在不考虑Bias的情况下,k个比特能够表达0到2^k−1的数字,但是我们把全1用来表达无穷大,把全0用来表示小于0的数,所以还剩下1到2^k−2部分。

表达分为三种:

  1. 当指数不是全0和全1的时候,我们称为normalized浮点数表示,指数E=e−Bias,其中e是(e_{k−1}e_{k−2}e_{k−3}...e_0)表达的无符号数。由于我们使用了全0的指数来表达绝对值小于1的数,我们认为这部分数的小数部分是M=1+f,其中f是(m_1m_2m_3...m_n)_2表示的小数部分,0\le f \le 1, 1\le 1+f \le 2
  2. 当指数全部都是0的时候,我们称为denormalized浮点表示,指数E=1−Bias,小数部分为M=f。这里需要注意的是当f的每个数位都为0的时候,f为0。但是s为0的时候表示+0,为1的时候表示-0。也就是IEEE 754B标准中0不唯一。
  3. 当指数全部为1的时候,我们表示无穷大。s为0的时候表示+\infty,为1的时候表示-\infty

考虑一个6比特的浮点数,其中我们使用1比特表示符号,3比特表示指数,2个比特表示小数。\text{Bias}=2^2−1=3

首先我们来看normalized浮点表示:
指数E_{max}=2^3−2−Bias=3, E_{min}=1−3=−2

而对于denormalized类型浮点:
指数E_{max}=1−Bias=1−3=−2

我们打印出除了无穷大之外的所有大于等于0的数如下表,小于0的部分只需要前面加上负号。

类型 二进制
normalized 2^3(1+\frac{1}{2}+\frac{1}{4})=14 0 110 11
normalized 2^3(1+\frac{1}{2}+0)=12 0 110 10
normalized 2^3(1+0+\frac{1}{4})=10 0 110 01
normalized 2^3(1+0+0)=8 0 110 00
normalized 2^2(1+\frac{1}{2}+\frac{1}{4})=7 0 101 11
normalized 2^2(1+\frac{1}{2}+0)=6 0 101 10
normalized 2^2(1+0+\frac{1}{4})=5 0 101 01
normalized 2^2(1+0+0)=4 0 101 00
normalized 2^1(1+\frac{1}{2}+\frac{1}{4})=3.5 0 100 11
normalized 2^1(1+\frac{1}{2}+0)=3 0 100 10
normalized 2^1(1+0+\frac{1}{4})=2.5 0 100 01
normalized 2^1(1+0+0)=2 0 100 00
normalized 2^0(1+\frac{1}{2}+\frac{1}{4})=1.75 0 011 11
normalized 2^0(1+12+0)=1.5 0 011 10
normalized 2^0(1+0+\frac{1}{4})=1.25 0 011 01
normalized 2^0(1+0+0)=1 0 011 00
normalized 2^{−1}(1+\frac{1}{2}+\frac{1}{4})=0.875 0 010 11
normalized 2^{−1}(1+\frac{1}{2}+0)=0.75 0 010 10
normalized 2^{−1}(1+0+\frac{1}{4})=0.625 0 010 01
normalized 2^{−1}(1+0+0)=0.5 0 010 00
normalized 2^{−2}(1+\frac{1}{2}+\frac{1}{4})=0.4375 0 001 11
normalized 2^{−2}(1+\frac{1}{2}+0)=0.375 0 001 10
normalized 2^{−2}(1+0+\frac{1}{4}14)=0.3125 0 001 01
normalized 2^{−2}(1+0+0)=0.25 0 001 00
denormalized 2^{−2}(\frac{1}{2}+\frac{1}{4})=0.1875 0 000 11
denormalized 2^{−2}(\frac{1}{2}+0)=0.125 0 000 10
denormalized 2^{−2}(0+\frac{1}{4})=0.0625 0 000 01
denormalized 2^{−2}(0+0)=0 0 000 00

对于32位的浮点数,使用了8位来表示指数,那么\text{Bias}=2^7−1=127

  1. normalized表示的时候, E_{max}=2^8−2−Bias=127, E_{min}=1−127=−126;
  2. denormalized表示的时候,E=1−127=−126

也就是说:

  • 大于0的最大的浮点数的比特为0 11111110 11111111111111111111111
  • 大于0的次大的浮点数的比特为0 11111110 11111111111111111111110
  • 大于0的次小的浮点数的比特为0 00000000 00000000000000000000010
  • 大于0的最小的浮点数的比特为0 00000000 00000000000000000000001

作者:杜凌霄
更多文章发布在公众号“探知轩”,欢迎关注。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容