C++数据类型

简介

C++数据类型包括基本内置类型、复合类型和自定义数据结构。

  • 基本内置类型:编译器内置的基本类型,包括算数类型(字符、整型数、布尔值、浮点数)和空类型void
  • 复合类型:基于其他类型定义的类型,包括数组、C风格字符串、指针、引用、C风格结构体(POD)和联合体(Union)
  • 自定义数据结构:用struct或者class定义的类

POD:Plain Old Data,用来表明C++中和C相兼容的数据类型,在C++中可以用is_pod<T>::value判断是否是POD类型。

内置类型

Tips:C++中整型大小因编译器和操作系统的不同而不同,通常人们假定short是16位,int是32位,long是32位,long long是64位。

实际开发中我们仅使用C++内置整型中的int,如果程序中需要大小不同的整型,那么:

  • 在合适情况下,推荐用size_tptrdiff_t
  • 我们可以认为int至少32位,如果需要使用64位整数,那么使用int64_t
  • 不要使用uint32_t等无符号类型,你应该使用断言来指出变量为非负数,混用有符号类型和无符号类型可能导致非预期的结果(见下文)

执行浮点数运算时使用double,因为float通常精度不够且双精度浮点数和单精度浮点数的计算代码相差无几

类型 类型名 占字节数 数值范围
整型 int(signed int) 4 -2147483648 \sim +2147483647 (-2^{31} \sim 2^{31}-1)
无符号整型 unsigned (unsigned int) 4 0 \sim 4294967295(0 \sim 2^{32}-1)
短整型 short(signed short) 2 -32768 \sim +32767(-2^{15} \sim 2^{15}-1)
无符号短整型 unsigned short 2 0 \sim 65535(0 \sim 2^{16}-1)
长整型 long (signed long) 4 -2147483648 \sim +2147483647(-2^{31} \sim 2^{31}-1)
无符号长整型 unsigned long 4 0 \sim 4294967295(0 \sim 2^{32}-1)
双长型 long long 8 -9223372036854775808 \sim 9223372036854775807(-2^{63} \sim 2^{63}-1)
字符型 char 1 -128 \sim +127(-2^7 \sim 2^7-1)
无符号字符型 unsigned char 1 0 \sim 255(0 \sim 2^8-1)
单精度型 float 4 -3.4×10^{38} \sim 3.4×10^{38}
双精度浮点型 double 8 -1.7×10^{308} \sim 1.7×10^{308}
长双精度浮点型 long double 8 -1.7×10^{308} \sim 1.7×10^{308}
布尔型 bool 1 true, false
空类型 void

字节byte:可寻址的最小内存块,大多数机器的字节由8比特构成

以我所在的64位机器为例:

#include <iostream>

int main() {
    std::cout << "size of int:" << sizeof(int) << std::endl;
    std::cout << "size of unsigned:" << sizeof(unsigned) << std::endl;
    std::cout << "size of short:" << sizeof(short) << std::endl;
    std::cout << "size of unsigned short:" << sizeof(unsigned short) << std::endl;
    std::cout << "size of long:" << sizeof(long) << std::endl;
    std::cout << "size of unsigned long:" << sizeof(unsigned long) << std::endl;
    std::cout << "size of long long:" << sizeof(long long) << std::endl;
    std::cout << "size of char:" << sizeof(char) << std::endl;
    std::cout << "size of unsigned char:" << sizeof(unsigned char) << std::endl;
    std::cout << "size of float:" << sizeof(float) << std::endl;
    std::cout << "size of double:" << sizeof(double) << std::endl;
    std::cout << "size of long double:" << sizeof(long double) << std::endl;
    std::cout << "size of bool:" << sizeof(bool) << std::endl;
}

// 输出:
size of int:4
size of unsigned:4
size of short:2
size of unsigned short:2
size of long:8
size of unsigned long:8
size of long long:8
size of char:1
size of unsigned char:1
size of float:4
size of double:8
size of long double:16
size of bool:1

类型转换

  • 当我们赋给无符号类型一个超过它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。比如8比特大小的unsigned char可以表示0~255,如果我们将-1赋给它将会得到255
  • 当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的,程序可能会继续工作、可能崩溃,也可能产生垃圾数据
  • 当一个算数表达式中既有无符号类型又有带符号类型时,带符号数会自动转化为无符号数,结果可能是出乎意料的:
// 切勿混用带符号类型和无符号类型
unsigned u = 10;
int i = -42;
std::cout << i + i << std::endl; // -84
std::cout << i + u << std::endl; // 如果int占32位则输出4294967264

字面值常量literal

1. 整形和浮点型字面量

以0开头的整数表示八进制,以0x或者0X开头的整数表示十六进制,我们可以用下面三种方式表示20:

20    // 十进制
024   // 八进制
0x14  // 十六进制

浮点型字面量是一个double,其中指数部分用E或者e标识:

3.14159
3.14159E0
0.
0e0
.001

2. 字符和字符串字面量

'a'表示一个字符;"a"字符串字面量包含字母a和空字符\0。当书写的字符串字面量比较长,我们可以采取分开书写的方式:

std::cout << "line one"
             "line two" << std::endl;

3. 布尔字面量与指针字面量

  • truefalse和布尔类型的字面量
  • nullptr是指针类型的字面量

引用

C++11新增了右值引用的概念,我们这里只提及左值引用。

引用为对象起了另一个名字,定义引用时程序把引用和它的初始值绑定在一起,一旦初始化完成引用将一直和它的初始值对象绑定在一起。

  • 因为无法令引用重新绑定到另一个对象,因此引用必须初始化
  • 因为引用不是一个对象,所以不能定义引用的引用

指针

指针是指向(point to)另外一种类型的复合类型。

1. 操作符&与*

获取对象地址时可以用&取地址符,利用指针访问对象时可以用*解引用符。

int iVal = 42;
int *p = &iVal;  // p是指向iVal变量的指针
cout << *p;      // 解引用获得p指向的对象 

2. 空指针

Tips:建议初始化所有指针,不清楚指向何处时初始化为nullptr

使用未经初始化的指针是引发运行时错误的一大原因,如果使用了未经初始化的指针,那么指针所占空间的当前内容将被当成一个地址值,当这个地址值指向的内存空间中正好有内容时,就可能引发难以预料的后果。实际开发过程中,我们尽量等定义了对象之后再定义指向它的指针,如果实在不清楚指针应该指向何处,那么将它初始化为nullptr,这样程序就能检测并指导它有没有指向任何具体的对象了。

C++11中我们可以用字面量nullptr初始化指针来得到空指针,它可以被转化成任意其他的指针类型。

3. void*

Tips:由于我们不知道void*指针指向什么类型的对象,因此不能直接操作它所指向的对象。

void*是一种特殊的指针类型,可以存放任意对象的地址,一般只能做如下操作:

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

自定义数据结构

C++允许用户以类的形式自定义数据类型,关于类的知识我们主要在后面的面向对象编程中讲解,这里简单给出一个例子:

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

推荐阅读更多精彩内容