Skip to content

Wiki

Data Types and Data Storage

About 17 min read

Existing English translations were reused. 7 current source blocks remain in Simplified Chinese, without triggering paid translation.

1.Data Type

1.1.Integer

作用:整型变量表示的是==整数类型==的数据

C++The types that can represent integers include the following,the difference lies in the amount of memory space occupied.

数据类型 占用空间 取值范围
short(短整型) 2字节 (-2^15 ~ 2^15-1)
int(整型) 4字节 (-2^31 ~ 2^31-1)
long(长整形) Linux x86-64 通常为8字节,Windows 64位通常为4字节 由实现的数据模型决定
long long(长长整形) 8字节 (-2^63 ~ 2^63-1)

注意:64 位系统不代表 long 一定占 8 字节。Windows 的 64 位数据模型仍然让 long 保持 32 位,指针扩展为 64 位;Linux x86-64 常用的数据模型不同。实际大小用下面的 sizeof 检查,不能只根据电脑是 32 位还是 64 位判断。参见 Windows 数据模型说明。

1.2.sizeof keyword

**Function:** The `sizeof` keyword can be used to ==determine the amount of memory occupied by a data type==.

Syntax: sizeof( 数据类型 / 变量)

Example:

int main() {
    // 程序从 main 函数开始执行,下面的语句会按顺序运行。

	cout << "short 类型所占内存空间为: " << sizeof(short) << endl;

	cout << "int 类型所占内存空间为: " << sizeof(int) << endl;

	cout << "long 类型所占内存空间为: " << sizeof(long) << endl;

	cout << "long long 类型所占内存空间为: " << sizeof(long long) << endl;


	// 返回 0 表示程序正常结束。
	return 0;
}

Run result (type size or type name may vary depending on compiler and platform):

short 类型所占内存空间为: 2
int 类型所占内存空间为: 4
long 类型所占内存空间为: 8
long long 类型所占内存空间为: 8

Windows 64 位环境中,上面示例的 long 一行通常会输出 4,其他几项通常仍是 2、4、8。比较类型大小时,用当前编译器实际输出的结果。

整型结论:==sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)==

1.3.Real type (floating-point type)

Function:used to ==represent decimals==

Floating-point variables are divided into two types:

  1. Single-precision float
  2. Double-precision double

The difference between the twolies inthe different ranges of significant digits they represent.

Data type Memory usage Significant digit range
float 4 bytes 7 significant digits
double 8 bytes 15–16 significant digits

Example:

int main() {

	float f1 = 3.14f;
	double d1 = 3.14;

	cout << f1 << endl;
	cout << d1<< endl;

	cout << "float  sizeof = " << sizeof(f1) << endl;
	cout << "double sizeof = " << sizeof(d1) << endl;

	//科学计数法
	float f2 = 3e2; // 3 * 10 ^ 2 
	cout << "f2 = " << f2 << endl;

	float f3 = 3e-2;  // 3 * 0.1 ^ 2
	cout << "f3 = " << f3 << endl;


	return 0;
}

Run result (type size or type name may vary depending on compiler and platform):

3.14
3.14
float  sizeof = 4
double sizeof = 8
f2 = 300
f3 = 0.03

1.4.Character type

**Function:** Character variables are used to display a single character

Syntax:char ch = 'a';

Note 1: When displaying character-type variables, enclose the characters in single quotes, not double quotes

Note 2: Only one character is allowed within single quotes; it cannot be a string.

  • C和C++中字符型变量只占用==1个字节==。
  • 字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元

Example:

int main() {
	
	char ch = 'a';
	cout << ch << endl;
	cout << sizeof(char) << endl;

	//ch = "abcde"; //错误,不可以用双引号
	//ch = 'abcde'; //错误,单引号内只能引用一个字符

	cout << (int)ch << endl;  //查看字符a对应的ASCII码
	ch = 97; //可以直接用ASCII给字符型变量赋值
	cout << ch << endl;


	return 0;
}

Run result (type size or type name may vary depending on compiler and platform):

a
1
97
a

ASCII code table:

ASCIIValue Control character ASCIIValue Character ASCIIValue Character ASCIIValue Character
0 NUT 32 (space) 64 @ 96 、
1 SOH 33 ! 65 A 97 a
2 STX 34 " 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 , 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 S 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 / 124 \|
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 `
31 US 63 ? 95 _ 127 DEL

The ASCII code is roughly composed of the followingtwo parts.

  • ASCII non-printing control characters: the numbers 0-31 in the ASCII table are assigned to control characters, which are used to control peripheral devices such as printers.
  • ASCII printable characters: the numbers 32-126 are assigned to characters that can be found on the keyboard and appear when a document is viewed or printed.

1.5.escape character

**Purpose:** Used to represent some ==ASCII characters that cannot be displayed==

At present, the escape characters we commonly use are: \n \\ \t

Escape Character Meaning ASCIICode value (decimal)
\a Alarm 007
\b Backspace (BS), moves the current position to the previous column 008
\f Form Feed (FF), moves the current position to the beginning of the next page 012
\n New Line (LF), moves the current position to the beginning of the next line 010
\r Carriage Return (CR), moves the current position to the beginning of the current line 013
\t Horizontal Tab (HT) (jumps to the next TAB position) 009
\v Vertical Tab (VT) 011
\\\\ Represents a backslash character "\" 092
\' Represents a single quote (apostrophe) character 039
\" Represents a double quote character 034
\? Represents a question mark 063
\0 Digit 0 000
\ddd Octal escape character, d ranges from 0 to 7 3-digit octal
\xhh Hexadecimal escape character, h ranges from 09, af, A~F 3-digit hexadecimal

Example:

int main() {
	// 程序从 main 函数开始执行,下面的语句会按顺序运行。
	
	
	cout << "\\" << endl;
	cout << "\tHello" << endl;
	cout << "\n" << endl;


	// 返回 0 表示程序正常结束。
	return 0;
}

Operation result:

\
	Hello

1.6.String type

Function:Used to represent a string of characters

Two styles

  1. C-style string: char 变量名[] = "字符串值"

    Example:

    int main() {
    
    	char str1[] = "hello world";
    	cout << str1 << endl;
        
    
    	return 0;
    }

Note: C-style strings must be enclosed in double quotation marks

  1. C++ style string: string 变量名 = "字符串值"

    Example:

    int main() {
    
    	string str = "hello world";
    	cout << str << endl;
    	
    
    	return 0;
    }

    ​

Note: C++ style string, need to include the header file ==#include\<string>==

1.7.Boolean type bool

**Purpose:** The Boolean data type represents a true or false value.

The bool type has only two values:

  • true --- True (essentially 1)
  • false --- False (essentially 0)

The bool type occupies ==1 byte== in size.

Example:

int main() {

	bool flag = true;
	cout << flag << endl; // 1

	flag = false;
	cout << flag << endl; // 0

	cout << "size of bool = " << sizeof(bool) << endl; //1
	

	return 0;
}

Run result (type size or type name may vary depending on compiler and platform):

1
0
size of bool = 1

1.8.Type alias typedef

C/C++ provides the typedef keyword, which you can use to give a new name to a type. The following example defines a term for a single-byte number, BYTE:

typedef unsigned char byte;
typedef unsigned char uint8_t;
typedef float fp32;
typedef double fp64;

Run result: This code block does not contain the main function; it is a syntax, interface, or multi-file example and cannot be run independently, so there is no terminal output.

1.9.Data Units, Binary, and Two's Complement

  1. 数据单位及其转换

    1. 1字节byte = 8比特bit = 8位二进制

    2. 数据是以 二进制 的形式存在电脑内存中的

    3. 进制转换

      1. 在C语言中,0b开头的数据代表2进制,0x开头的数代表16进制。因为2进制较长,所以我们在代码中,一般把2进制转化成16进制进行表示。
    4. 数据的原码

      1. 无符号(unsigned)的数据类型: 无符号数据所占的所有2进制都表示数据的大小,假设占8位2进制,那么该数最大是255(其对应的2进制:1111 1111),最小是0(对应2进制是0000 0000)。

      2. 有符号(signed)的数据类型:有符号的数据其最高位二进制是符号位,符号位是0则是正数,符号位是1则为负数。假设占8位2进制,去掉1位2进制,还剩7位2进制来表示数据的大小。那么其最大是127(其2进制是0111 1111),最小是-128(其2进制是1000 0000,-127的是1111 1111),这个-128其实是用了-0的二进制表示,因为咱们有0(0000 0000)了,所以-0(理论是1000 0000)就没有啥意义了,所以我们规定把-0的二进制表示成-128。

    5. 数据的命名 :

      1. 由于unsigned char,int等数据类型名称无法突出 数据的二进制 有无符号,占多少二进制,所以我们用typedef给其起新的别名(比如 新别名 uint8_t,int32_t)

        1. uint8_t 中的u代表unsigned无符号,8代表占8位二进制,也就是1个字节。

        2. int32_t前面不带u,所以是有符号的,占32位二进制,所以也就是占4个字节,所以是int类型的别名

        3. 因为char 占 1 字节,8 比特,8 位二进制,而且有符号,所以我们叫他int8_t

        4. 因为unsigned short int 无符号,占 2字节,16比特,16位2进制,所以叫uint16_t,其他的类似。

        5. float占4字节,32位二进制,所以叫fp32

        6. double占8字节,64位二进制,所以叫fp64

      2. 具体的代码(在C++中自带一部分别名,可以不写一部分别名,但建议写):

        1. typedef unsigned char uint8_t;

        2. typedef short int int16_t;

        3. typedef unsigned int uint32_t;

        4. typedef float fp32;

  2. 数据解析:

    1. 应用场景介绍:一般传感器会一直给我们的单片机、工控机发送数据,比如说发送我们机器人所走的路程(假设单位是毫米,是个短整型数)。

    2. 数据处理目标: 比如获取路程(短整型,2个字节,16位2进制)

    3. 传感器传数据: 一般的通信来说,传感器会一个字节一个字节的给单片机和工控机不断发数据,一般一个占n字节的物理量数据,要分成n个字节,也就是n个变量来发,又因为数据以2进制的形式存储,一般先发最高的8位二进制。

    4. 单片机、工控机接受到的数据: 比如获取机器人的路程,该数据占2字节,所以传感器要分成两个变量来发送。先接收到的变量我们叫DH(数据的高8位2进制),后接收到的数据我们叫DL(数据的低8位2进制)。

    5. 数据处理思路: 我们现在拥有的是两个普通的8位二进制变量(uint8_t类型的),我们想要获得带符号的16位2进制的数据,机器人的路程(int16_t类型的)。

      1. 位操作 : 假如说,DH是0x9D(对应2进制是1001 1101),DL是0x57(对应2进制是0101 0111)。那么我们想要的16位数据就是把DH当16位中的最高的8位,DL当最低的8位,也就是我们想要的数据DATA(其二进制是 1001 1101 0101 0111)。我们想实现这个效果,就需要位操作,把DH向左移8位,让他变成1001 1101 0000 0000,然后再把左移后的DH 与 DL进行按位或运算,也就是1001 1101 0000 0000 与 0000 0000 0101 0111进行按位或,最后就得出来DATA是1001 1101 0101 0111了。

      2. 强转类型: 我们上面已经得出来data的2进制了,再进行强转化成有符号的数,也就是把最高位中的1变成符号位,具体代码是int16_t DATA = (int16_t) ((uint16_t)DH << 8 | DL ),这样就处理成功了。

  3. 数据在内存中的二进制表示方式

    1. 计算机存储数据的前置知识

      1. 计算机底层存储数据时使用的是二进制数字,但是计算机在存储一个数字时并不是直接存储该数字对应的二进制数字,而是存储该数字对应二进制数字的 补码 。

      2. 机器码:一个数在计算机的存储形式是二进制数,我们称这些二进制数为机器数,机器数是有符号,在计算机中用机器数的次最高位的左侧存放符号位,0表示正数,1表示负数

      3. 真值:因为机器数带有符号位,所以机器数的形式值不等于其真实表示的值(真值),以机器数1000 0001为例,其真正表示的值(首位为符号位)为-1,而形式值(首位就是代表1)为129; 因此将带符号的机器数的真正表示的值称为机器数的真值 。

    2. 原码、反码、补码:

      1. 原码 的表示与机器数真值表示的一样,即用第一位表示符号,其余位表示数值。也就是

          正数:就是它对应的二进制数。 负数:将绝对值对应的二进制最左边位变为1。

      【+1】= 原:[ 0000 0001 ]
      【-1】= 原:[ 1000 0001 ]
      1. 反码:

          正数 : 和原码相同。 负数 : 在其原码的基础上,符号位不变,其余各位取反。

      【+1】= 原: [ 0000 0001 ] = 反:[ 0000 0001 ]
      【-1】= 原: [ 1000 0001 ] = 反:[ 1111 1110 ]
      1. 补码 :

          正数 : 补码是其原码本身。 负数 : 补码是在其原码的基础上,符号位不变,其余各位取反后加1(即在反码的基础上加1)

      【+1】= 原: [ 0000 0001 ] = 反:[ 0000 0001 ] = 补:[ 0000 0001 ]
      【-1】= 原: [ 1000 0001 ] = 反:[ 1111 1110 ] = 补:[ 1111 1111 ]
    3. 数据在计算机中的存储形式

      1. 计算机实际只存储补码,所以原码转换为补码的过程,也可以理解为数据存储到计算机内存中的过程:

      1. 正数:在原、反、补码中,正数的表示是一模一样的

      2. 负数:负数的表示是不相同的,所以对于负数的补码来说,我们是不能直接用进制转换将其转换为十进制数值的,因为这样是得不到计算机真正存储的十进制数的,所以应该将其转换为原码后,再将转换得到的原码进行进制转换为十进制数(机器数包含符号位)

      3. 为什么要诞生原码、反码和补码?

        1. 原因:对于只有正数的加减运算来说,用原码计算是没有任何问题的,但是当既有正数,也有负数的时候,计算机无法判断最高位是否是符号位。
    4. 总结:

      1. 二进制的最高位是符号位:0表示正数,1表示负数

      2. 正数的原码反码补码都一样,三码合一。

      3. 负数

        1. 负数的反码 = 它的原码符号位不变,其它位取反。

        2. 负数的补码 = 它的反码 + 1, 负数的反码 = 负数的补码 - 1 。

      4. 0 的反码、补码都是 0 。

      5. 在计算机运算的时候都是以 “补码” 的方式来运算的。

      6. 运算结果是以 原码 形式展现的。