C++学习笔记(一)

C++学习笔记(一)

十月 01, 2021

前言:

这部分学习C++的数据处理


数据处理

整型

C++拥有四种整型类型,分别是:

  • short: 16位
  • int: 16位
  • long: 32位
  • long long: 64位

不同系统中不同整型的最大长度可能不同,可以使用C++内置的sizeof运算符来返回类型或变量长度,单位为字节。或者可以使用climits头文件,该同文件中定义了各种限制的符号名称,其中包含整型限制的信息,例如INT_MAX表示int类型的最大取值,CHAR_BIT为字节位数。下面是使用Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <climits>

int main() {
using namespace std;
int n_int = INT_MAX;
short n_short = SHRT_MAX;
long n_long = LONG_MAX;
long long n_llong = LLONG_MAX;

cout << "int is " << sizeof(int) << " bytes." <<endl;
cout << "short is " << sizeof n_short << "bytes" <<endl;
cout << "long is " << sizeof n_long << "bytes" <<endl;
cout << "long long is " << sizeof n_llong << "bytes" <<endl;
cout <<endl;

cout << "Maximum values:" <<endl;
cout << "int: " << n_int <<endl;
cout << "short: " << n_short <<endl;
cout << "long : " << n_long <<endl;
cout << "long long: " << n_llong <<endl <<endl;

cout << "Bits per byte = " << CHAR_BIT << endl;
return 0;
}

对于类型名(如int)使用sizeof运算符是,应将名称放在括号内,但是对于变量名,括号是可选的。

符号常量定义和变量初始化

climits头文件中包含大量类似于#define INT_MAX 32767的语句行。在C++编译过程中,首先将源代码传递给预处理器。在这里,#define#include是一样的,都是一个预处理器编译指令。该编译指令告诉预处理器:在程序中查找INT_MAX,并将其替换为32767。这是C++留下来的特性,C++可以使用关键词const创建符号常量。所以如果不是在设计成C和C++均可用的头文件中,#define指令很少被使用。

变量的初始化,除了使用C语言传统的int n_int = 101意外,还可以使用C++ 的特有形式int n_int(101)

注意:如果不对函数内部定义的变量进行初始化,该变量的值将是不确定的。这意味着该变量的值将是它被创建之前,相应内存单元内保存的值

除此之外,C++98还可以使用大括号进行单值变量的赋值,具体方式如下:

1
2
3
int hamburgers = {24};
int emus{7};
int roces = {}; // set rocs to 0

上列的方式均是可以正确初始化变量的。

无符号类型

之前介绍的四种整型均有其对应的无符号整型,作用在于扩大变量可以存储的最大值。创建无符号版本的基本类型,只需使用关键字unsigned来修改即可:

1
2
3
4
5
unsigned short ushort;
unsigned int uint;
usingned uint; // also unsigned int
usigned long ulong;
unsigned long long ullong;

下面这个Demo将演示如何使用无符号整型,以及当程序试图超越类型限制时将会导致怎样的后果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <climits>

#define ZERO 0;

int main() {
short sam = SHRT_MAX;
unsigned short sue = sam;

std::cout << "Sam has " << sam << " dollars and Sue has " << sue;
std::cout << " dollars deposited." <<std::endl;

sam = sam + 1;
sue = sue + 1;
std::cout << "Sam has " << sam << " dollars and Sue has " << sue;
std::cout << " dollars deposited.\nPoor Sam!" << std::endl;

sam = ZERO;
sue = ZERO;
std::cout << "Sam has " << sam << " dollars and Sue has " << sue;
std::cout << " dollars deposited." << std::endl;
std::cout << "Take $1 from each account." << std::endl << "Now ";
sam = sam - 1;
sue = sue - 1;
std::cout << "Sam has " << sam << " dollars and Sue has " << sue;
std::cout << " dollars deposited." << std::endl << "MLucky Sue!" << std::endl;
return 0;
}

输出结果为:

1
2
3
4
5
6
7
Sam has 32767 dollars and Sue has 32767 dollars deposited.
Sam has -32768 dollars and Sue has 32768 dollars deposited.
Poor Sam!
Sam has 0 dollars and Sue has 0 dollars deposited.
Take $1 from each account.
Now Sam has -1 dollars and Sue has 65535 dollars deposited.
MLucky Sue!

这是因为数字以补码的形势存储,而我们的操作让short变量上溢和unsigned short下溢。

整型字面量

C++使用三种不同的整型字面量形势,分别是:

  • 第一位为1~9,基数为10
  • 第一位为0,基数为8,如043
  • 前两位为0x或0X,基数为16

如果想以十六进制或八进制的方式显示值,可以使用cout的dec、hex和oct控制符,分别用以表示之后的数据流用十进制、十六进制和八进制显示数值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

int main() {
using namespace std;

int chest = 42;
int waist = 42;
int inseam = 42;

cout << "Monsieur cuts a striking figure!" << endl;
cout << "chest = " << chest << " (decimal for 42)" << endl;
cout << hex;
cout << "waist = " << waist << " (hexadecimal for 42)" << endl;
cout << oct;
cout << "inseam = " << inseam << " (octal for 42)" << endl;
return 0;
}

由于标识符hex位于命名空间std中,而程序使用了该名称空间,因此不能再将hex作为变量名使用。如果不使用编译指令using,而是使用std::hex的形势,则hex仍可以作为变量名使用。

常量类型

除非使用特殊后缀来表示特定类型或者值太大等情况往外,C++一律将整型常量存储为int类型。类型后缀有

  • long类型后缀:l或L
  • unsigned int类型后缀:u或U
  • unsigned long类型后缀:uL
  • unsigned long long类型后缀:ull Ull uLL ULL

char类型

char类型除了可以用来存储字符,也可以当作比short更短的整型使用

bool类型

布尔类型,可以使用字面量true和false表示,任何非0的值都将被转换成true,0会被转换成false。

const限定符

const限定符表示其定义的值为一个常量,定义之后编译器将不再允许修改该常量的值。需要注意的是,应在声明常量时就初始化其值

1
2
const int toes;
toes = 10;

这种形式是不被允许的,且常量toes的值不确定。

浮点数

C++有3种浮点烈性,float、double和long double。其中float至少32位,double至少48位。

浮点常量:默认情况下常量小数均为double类型,如果希望常量位float类型,需要使用f或F后缀,如果希望是long double类型,可以使用L后缀

除法

在C++种,如果除法运算符的两个操作数都是整数,则C++将执行整数除法,只保留运算结果的整数部分。如果至少有一个操作数是浮点数,则最终结果位浮点数

类型转换

为了预防潜在的混乱,C++会在以下情况自动执行类型转换:

  • 将一种算数类型的值赋给另一种算数类型的变量时
  • 表达式中包含不同的类型时
  • 将参数传递给函数时

初始化和赋值进行的转换: C++允许将一种类型的值赋给另一种类型的变量。这样做时,值将被转换为接收变量的类型。例如将short类型的thirty赋值给long类型的so_long,则程序会将thirty的值从16位扩展到32位,赋值给so_long,thirty本身的值不变。

表达式中的转换:

在计算表达式时,C++会将bool、char、unsigned char、signed char和short类型转换为int。然后编译器会一次执行下列的转换判断:

  • 如果有一个操作数类型为long double,则转换为long double
  • 如果有一个操作数的类型是double,则将另一个操作数转换为double
  • 如果有一个操作数的类型是float,则将另一个操作数转换为float
  • 否则,则说明操作数都是整型,因此执行整型提升
  • 如果两个操作数都是有符号或者无符号,且其中一个操作数的级别比另一个地,则转换为级别高的类型

强制类型转换:

可以使用以下两种形式进行强制类型转换:(long) valuelong (value)

auto声明:

C++新增了auto定义方式,让编译器能够根据初始值的类型推断变量的类型。在初始声明中,使用关键字auto,而不置顶变量的类型,编译器将把变量的类型设置成雨初始值相同

复合类型

数组

数组声明应指出以下三点:

  • 存储在每个元素中的值的类型
  • 数组名
  • 数组中的元素数

例如:short months[12],其中元素数必须是整型常量或常量表达式,即其中所有的值在编译时是已知的,不能为变量。

只有在定义数组时才能使用初始化

字符串

字符串常量使用双引号,字符常量使用单引号。

任何两个由空格分隔的字符串常量都将自动拼接成一个

结构

结构是用户定义的类型,而结构声明定义了这种类型的数据属性。定义了类型后,便可以创建这种类型的变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>

using namespace std;

struct inflatable {
string name;
float volume;
double price;
};

int main() {
inflatable guest = {
"Glorious Gloria",
1.88,
29.99
};
cout << "Expand your guest list with" << guest.name;
cout << " and " << guest.price << endl;
}

结构如果声明在函数外部,则称为外部声明,对于所有函数均可用,如果声明在函数内部,则称为内部声明,只在函数内部起作用

共用体

共用体是一种数据格式,它能存储不同类型的数据,但是同时只能存储其中一种类型。

1
2
3
4
5
6
7
8
union one4all {
int int_val;
long long_val;
double double_val;
};
one4all pail;
pail.int_val = 15;
pail.double_val = 1.38 // store a double, int value lose

匿名共用体没有名称,其成员将成为位于相同地址的变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct widget {
char brand[20];
int type;
union {
long id_num;
char id_char[20];
};
};

widget prize;

if (prize.type == 1) {
cin >> prize.id_num
} else {
cin >> prize.id_char
}

枚举

C++提供枚举工具enum

1
2
3
4
enum spectrum { red, orange, yellow, green, blue, violet, indigo, ultraviolet};
spectrum band;
band = blue; // valid
band = 200; // invalid

在默认情况下,会将整数值赋值给枚举量,第一个枚举量为0,第二个为1,依次递增。可以指定一个枚举量为整数,后面没初始化的枚举量将比前面的枚举量大1

指针

对变量使用地址运算符(&)即可获得变量的指针。

加入一个变量存储的是地址,则我们可以使用*运算符获得该地址的值

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

int main() {
using namespace std;
int updates = 6;
int * address_updates;
address_updates = &updates;

cout << address_updates <<endl;
cout << * address_updates <<endl;
return 0;
}

C++可以使用new来分配内存,然后在内存存储值

1
2
3
4
5
6
7
8
9
#include <iostream>
int main() {
using namespace std;
int * pt = new int;
*pt = 1001;
cout << *pt <<endl;
delete pt;
return 0;
}

可以通过delete来释放内存,delete只能用来释放使用new创建的内存空间

指针变量加减,加减的是它指向类型的字节数

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
int main() {
using namespace std;
double * p = new double[3];
cout << p[0] << endl;
p[0] = 1.0;
p[1] = 2.0;
p[2] = 3.0;
cout << p[0] << endl;
p = p + 1;
cout << p[0] << endl;
return 0;
}