1.数组基础
1.1 数组的定义
// typeName arrayName[arraySize]
long productIds[199];
1.2 数组的优点和缺点
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
long productIds[199];
//优点:可以随意获取数组元素
productIds[0] = 20;
productIds[1] = 30;
productIds[2] = productIds[0] * productIds[1];
/*缺点:对数组元素进行插入/删除,会导致整个数组的移动,具体移动的个数,取决于所插入/删除得元素在数组中的所在位置*/
return 0;
}
1.3 获取数组的长度
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
long productIds[199];
productIds[0] = 20;
productIds[1] = 30;
productIds[2] = productIds[0] * productIds[1];
cout << "数组占的总字节数:" << sizeof productIds << endl; //打印1592
cout << "数组长度:" << sizeof productIds / sizeof(long) << endl; //打印199
return 0;
}
2.数组初始化
2.1 传统的数组初始化方式
//正确
int number[4] = {3,6,9,12};
//错误
int productIds[4];
productIds[3] = {1,2};
//错误,不能用一个数组名初始化另一个数组
productIds = number;
//正确 没有进行初始化的数组元素都会设为0
float values[5] = {5.0,2.1};
2.2 数组清零(传统的方式和C++ 11中的方式)
//传统方式
float totals[200] = {0};
//C++11中的方式
float totals[200] = {}; //全零
2.3 C++ 11中的数组初始化方式
double c11_values1[4] {1.2,3.3,4.4,5.5}; //可以不需要等号
double c11_values2[] {1.2,3.3,4.4,5.5}; //可以不指定长度,会自动检测
2.4 C++ 11中的数组元素类型检测
short years[] = {25, 12,1.0}; //会报错,1.0默认为double类型,无法转换成short
char c_array[] = {'a','b',123}; //char最多能表示到127,所以123是可以转换成char的
int x = 123;
char c_array1[] = {'a','b', x}; //报错,C++编译器无法继续检测x的类型/范围
int x = 123;
char c_array1[] = {'a','b',(char)x}; //正确
3.C风格的字符串
3.1 C风格字符串的存储格式
在字符串结尾有一个ASCII值为0的字符,即转义字符' \0 ',当系统读到' \0 '时,就会认为字符串结束,无论' \0 '后面有什么,全部扔掉。
3.2 C风格字符串变量的定义和初始化
//定义C风格的字符串有两种方式: 1.数组 2.指针
//1.数组
char str1[6] = {'a','b','c','d','e','\0'}; //是一个字符串,转义字符占用一个位置
char str2[6] = {'a','b','c','d','e','f'}; //不是字符串,只是一个普通的char类型数组
char str1[6] = {'a','b','c','\0','e','\0'};
cout << str1 << endl; //打印: abc
char str1[6] = {'a','b','c','d','e','\0'};
cout << str1 << endl; //打印: abcde
char str1[6] = {'a','b','c','\0','e','\0'};
cout << *(str1+4) << endl; //打印: e
char str3[6] = "abc"; //给'\0'预留了位置,是字符串
char str4[] = "abcdefdsfslfsdjsdfljjlsdljfd"; /*也可以不指定空间的字节数,C++编译器会自动检测长度,并在后面加上'\0' */
//2.指针
char *pstr = "abcd"; //自动分配了5字节空间(包括了'\0')
cout << pstr << endl;
3.3 字符串连接
char str5[] = "abcd""abc"; //打印:abcdabc
cout << str5 << endl; //不能连接字符串与字符串变量
cout << "xyz""123" << endl; //打印 xyz123
3.4 获取字符串长度
char str3[6] = "abcde";
cout << strlen(str3) << endl; //打印 5
char str3[6] = "abc";
cout << strlen(str3) << endl; //打印 3 和数组大小无关,长度不包含'\0'的部分
3.5 枚举字符串中的字符
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
char str3[6] = "abc";
int n = strlen(str3);
//数组的方式
for(int i = 0; i < n; i++)
{
cout << "<" << str3[i] << ">";
}
cout << endl;
//指针的方式
for(int i = 0; i < n; i++)
{
cout << "<" << *(str3 + i) << ">";
}
cout << endl;
return 0;
}
//打印 <a><b><c>
4.C风格字符串的输入
4.1. cin >> ...输入方式
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
int size = 10;
char name[size]; //size = 10 但最多存9个字符
cout << "请输入你的名字:";
cin >> name;
//name[9] = '\0';
cout << "你的名字是:" << name << endl;
return 0;
}
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
int size = 10;
char name[size]; //size = 10 但最多存9个字符
cout << "请输入你的名字:";
cin >> name;
name[9] = '\0'; //可以防止即使输入字符串长度超过9,也能正常输出
cout << "你的名字是:" << name << endl;
return 0;
}
4.2. getline输入方式
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
char city[20];
cout << "请输入你所在的城市:";
cin >> city;
cout << "你所在的城市是:" << city << endl;
return 0;
}
//当输入中间带有空格的内容时,比如New York,只会打印 New
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
char city[20];
char s[20];
cout << "请输入你所在的城市:";
cin >> city >> s;
cout << "你所在的城市是:" << city << endl;
cout << s << endl;
return 0;
}
//输入New York时,把New给到city,把York给到s,但输出是分开的
// istream.getline方法
cin.getline(city, 20); //读到回车会自动忽略回车,最多输入19个字符,最后一个字符被设为'\0'
cout << "你所在的城市是:" << city << endl;
4.3. get输入方式
此时输入New York,按回车会打印:
因为get区别于getline,get会读取回车符,那么此时city1读取到了New York,city2读取了空行,并按回车进行了输出。解决方法如下:
// 方法一
char city1[20];
char city2[20];
cout << "城市1:";
cin.get(city1, 20);
cin.get(); //把回车消耗掉
cout << "城市2:";
cin.get(city2, 20);
cout << "城市1:" << city1 << endl;
cout << "城市2:" << city2 << endl;
// 方法二
char city1[20];
char city2[20];
cout << "城市1:";
cin.get(city1, 20).get(); //效果等同于上者,只是形式不同
cout << "城市2:";
cin.get(city2, 20);
cout << "城市1:" << city1 << endl;
cout << "城市2:" << city2 << endl;
4.4. 字符串和数字混合输入
int year;
char name[20];
(cin >> year).get(); // 把回车吃掉,若不吃掉,则getline会把回车符当作输入
cin.getline(name, 20);
cout << "year:" << year << endl;
cout << "name:" << name << endl;
5.C++风格的字符串:string类
5.1 声明string类型的变量
char str1[] = "hello world"; //C风格声明字符串
string str2 = "hello world"; //C++风格,string属于标准命名空间std中
C++风格的字符串后面没有'\0'
5.2 初始化string类型的变量(包括C++ 11的初始化方式)
string str3 = {"Hello world"};
string str4 {"hello world"}; // C++ 11
5.3 输入输出string类型的变量值
cout << "请输入str1:";
cin >> str1;
cout << "str1=" << str1 << endl;
cout << "请输入str2:";
cin >> str2;
cout << "str2=" << str2 << endl;
5.4 获取string类型变量值中的指定字符
for(int i = 0; i < str2.length();i++)
{
cout << "<" << str2[i] << ">" << endl;
}
6.字符串的复制、连接和获取长度
6.1 字符串的复制
// C++字符串的复制
string str1 = "abc";
string str2 = str1;
cout << "str2 = " << str2 << endl;
//str1.c_str()将C++风格的字符串转换为C风格的字符串
const char *p = str1.c_str();
cout << "p=" << p << endl;
// C字符串的复制--strcpy
char c_str1[] = "hello";
char c_str2[6]; //当c_str2大小为4时,就只能复制3个字符到c_str2了
strcpy(c_str2,c_str1); //strcpy(目标字符串,源字符串);
cout << "c_str2=" << c_str2 << endl;
// C字符串的复制--strncpy
char c_str1[] = "hello";
char c_str2[4];
strncpy(c_str2,c_str1,3); //strncpy(目标字符串,源字符串,复制字符串的长度(不包含'\0'));
cout << "c_str2=" << c_str2 << endl;
6.2 字符串的连接
// C++字符串连接
str2 += str1; // str2 = str2 + str1;
cout << "str2=" << str2 << endl;
// C字符串连接
//hello和空格占了6个字符位置,再加上'\0',一共占了7个位置,最多再往里放三个字符
char c_str3[10] {"hello "};
char c_str4[] {"world"};
// strcat(c_str3, c_str4); //strcat(前面的字符串, 后面的字符串);
//即,将c_str4中的字符放入c_str3中,所以要保证c_str3有足够的空间
strncat(c_str3, c_str4, 3); //只能在后面追加3个字符
cout << "c_str3=" << c_str3 << endl;
6.3 获取字符串长度
// 获取字符串的长度
int len1 = str1.length(); // C++风格字符串
int len2 = strlen(c_str3); // C风格字符串
7.宽字符串与Raw String
7.1 宽字符串
string str1 = "中花"; //C++风格字符串
char c_str[] = "中"; //C风格字符串,通过数组方式定义
wchar_t wc_str[] = L"中"; //宽字节,有符号类型 32位 4字节 在定义时前加前缀L
cout << "str1 length:" << str1.length() << endl; //C++风格获取字符串长度,字符个数
cout << "c_str length:" << sizeof(c_str) / sizeof(char) << endl;
cout << "c_str byte length:" << sizeof(c_str) << endl; //字节长度
cout << "wc_str length:" << sizeof(wc_str) / sizeof(wchar_t) << endl;
cout << "wc_str byte length:" << sizeof(wc_str) << endl;
①对于str1,是C++风格的字符串,不考虑'\0',每个中文占3字节
②对于c_str,是C风格的字符串,考虑'\0',中文占用3字节,'\0'占1字节,所以共有4个char,每个char1字节,总长度4字节
③对于宽字节wchar_t,不管是什么字符,都占用4字节,即'\0'也占用4字节,所以共有2个wchar_t,总字节长度为8
输出结果:
// char16_t 无符号类型 2字节 在定义时前加前缀u
// char32_t 无符号类型 4字节 在定义时前加前缀U 等同于wchar_t
char16_t w16_char[] =u"中";
cout << "w16_char length:" << sizeof(w16_char) / sizeof(char16_t) << endl; // 2
cout << "w16_char byte length:" << sizeof(w16_char) << endl; // 4
7.2 Raw String
cout << "Hello \\n World" << endl; //想要直接输出\n,需要加转义字符
//无需加转义字符,括号中的内容不做任何处理,记得加括号
cout << R"(Hello \n \n \ World)" << endl;
cout << R"((Hello \n \n \ World))" << endl; //再加一层括号,就能输出括号了
//括号的开头和结尾部分要匹配,即,开头部分加xyz的话,末尾部分也要加,才能把中间的内容原样输出
cout << R"xyz((Hello \n (aa)\n \ World))xyz" << endl;
8.结构体的定义、初始化和使用
8.1 结构体的定义
// 可以在函数里/外定义 ,几种写法
struct MyStruct
{
int code;
string name;
float salary;
} myStruct1;
// 几种写法
MyStruct myStruct5 = MyStruct();
MyStruct myStruct2; // C语言需要在最前方添加struct关键字,C++不需要
auto myStruct3 = new MyStruct(); //auto会自动识别为结构体指针
auto mySturct4 = MyStruct();
8.2 结构体的初始化
struct MyStruct
{
int code;
string name;
float salary;
} myStruct1 = {20,"bill", 2550};
MyStruct myStruct5 = MyStruct(); //无法初始化,只能一个一个的修改成员变量
MyStruct myStruct2 = {20,"bill", 2550}; // C语言需要添加struct关键字,C++不需要
MyStruct myStruct2 {20,"bill", 2550}; //C++11
auto myStruct3 = new MyStruct();
auto mySturct4 = (MyStruct){20,"bill", 2550};
8.3 结构体的使用
auto myStruct3 = new MyStruct(); // myStruct3是指针
auto mySturct4 = (MyStruct){20,"bill", 2550}; // mySturct4是结构体变量
mySturct4.code = 200;
mySturct4.name = "abc";
mySturct4.salary = 20.3;
cout << mySturct4.name << endl;
// myStruct3是结构体指针
myStruct3->name = "ABC";
9.结构体数组
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
struct MyStruct
{
int code;
string name;
int values[2];
};
MyStruct myStructArray1[100]; //定义了一个结构体类型的数组
myStructArray1[0].name = "bill"; //设置结构体数组中第一个元素的成员变量name
cout << myStructArray1[0].name << endl;
//初始化结构体数组,方式一
MyStruct myStructArray2[2] = {{20, "Mary",{1,2}}, {30, "John", {3,4}}}; //全部花括号
cout << myStructArray2[0].values[1] << endl;
/* 初始化结构体数组,方式二,用auto时,等号右侧的内容一定要能定义左侧的类型,所以才要加上(MyStruct[]) */
auto myStructArray3 = (MyStruct[]){{20, "Mary",{1,2}}, {30, "John", {3,4}}};
cout << myStructArray3[1].name << endl;
return 0;
}
10.计算结构体的尺寸
10.1 结构体尺寸的计算规则
在默认情况下,结构体尺寸是结构体中占字节最多的成员变量的尺寸的整数倍
更通用的说法:结构体尺寸是当前对其方式的整数倍
struct MyStruct1
{
int code1;
int code2;
};
cout << "MyStruct1 size:" << sizeof(MyStruct1) << endl; // 8
struct MyStruct2
{
short code1;
char c;
} myStruct2{20,'a'};
cout << "MyStruct2 size:" << sizeof(MyStruct2) << endl; // 4
10.2 结构体的对齐方式
struct MyStruct2
{
short code1;
char c;
} myStruct2{20,'a'};
unsigned int *n1 = (unsigned int*)&myStruct2; //n1是地址(指针),指向结构体
bitset<32> b1(*n1);
cout << "myStruct2二进制表示:" << b1 << endl; // 00000000011000010000000000010100
从低位往高位存,20存到低16位,再存'a'
'a' : (十进制ASCII)97 (二进制) 01100001 —— char类型 1字节 8位 对齐补零后:16位
20 :(二进制) 0000000000010100 —— short类型 2字节 16位
// 如果结构体成员变量默认的对齐方式与修改后的对齐方式冲突,以最小的为准
struct MyStruct3
{
char c;
short code1;
} myStruct3{'a',20}; // 20和'a'进行了调换
cout << "MyStruct3 size:" << sizeof(MyStruct3) << endl;
// 结构体的对齐方式
unsigned int *n2 = (unsigned int*)&myStruct3;
bitset<32> b2(*n2);
cout << "myStruct3二进制表示:" << b2 << endl; // 4
10.3 修改结构体默认的对齐方式
//如果结构体成员变量默认的对齐方式与修改后的对齐方式冲突,以最小的为准
#include <iostream>
using namespace std;
#pragma pack(1) //改变对齐方式 :以1字节为单位,结构体尺寸是1字节的整数倍
int main(int argc, const char * argv[])
{
struct MyStruct2
{
short code1;
char c;
} myStruct2{20,'a'};
// 默认对齐方式:2 修改后的对齐方式:1 ,以1为准
cout << "MyStruct2 size:" << sizeof(MyStruct2) << endl; // 3
return 0;
}
#include <iostream>
using namespace std;
#pragma pack(2) //改变对齐方式 :以2字节为单位,结构体尺寸是2字节的整数倍
int main(int argc, const char * argv[])
{
struct MyStruct2
{
short code1;
char c;
} myStruct2{20,'a'};
cout << "MyStruct2 size:" << sizeof(MyStruct2) << endl; // 4
return 0;
}
#include <iostream>
using namespace std;
#pragma pack(4) //如果结构体成员变量默认的对齐方式与修改后的对齐方式冲突,以最小的为准
int main(int argc, const char * argv[])
{
struct MyStruct2
{
short code1;
char c;
} myStruct2{20,'a'};
// 默认对齐方式:2 修改后的对齐方式:4 ,以2为准
cout << "MyStruct2 size:" << sizeof(MyStruct2) << endl; // 4
return 0;
}
10.4 空结构体的尺寸
struct NullStruct
{
};
cout << "NullStruct Size:" << sizeof(NullStruct) << endl; // 1
总是1 ,不受#pragma pack(1)影响
11.结构体的位字段
11.1 定义、初始化位字段
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
struct MyStruct1
{
unsigned int code1;
unsigned int code2;
bool flag;
};
struct MyStruct2
{
unsigned int code1:4; //占了4位
unsigned int code2:4;
bool flag:1;
} myStruct2{17,15,false};
cout << sizeof(MyStruct1) << endl; //12字节
/* 4字节 ,默认对齐是4字节,那么MyStruct2的尺寸应该是4的整数倍,因为MyStruct2一共占9位,那么4字节够用了 */
cout << sizeof(MyStruct2) << endl; //4字节
cout << myStruct2.code2 << endl; //打印: 1 为什么?
struct MyStruct3
{
unsigned int code1:18; //占了18位
unsigned int code2:14;
bool flag:1;
} myStruct3{17,15,false};
//8字节,MyStruct3一共占了33位,4字节不够用了,所以是8字节
cout << sizeof(MyStruct3) << endl;
11.2 位字段是如何存储的?如果位字段溢出,会发生什么?
struct MyStruct2
{
unsigned int code1:4;
unsigned int code2:4;
bool flag:1;
} myStruct2{17,15,false};
cout << myStruct2.code2 << endl; //打印: 1 为什么?
// 以二进制形式输出
unsigned int *n = (unsigned int*)(&myStruct2);
bitset<32> b(*n);
cout << b << endl; //打印 00000000000000000000000011110001
存储方式:从结构体的第一个成员开始,从低位往高位存,即:
00000000000000000000000 0 1111 0001
false 15 17
myStruct2.code1只取存储中的低四位,又因为17对应的二进制是 10001,所以17被截断了,只剩下0001
12.共用体或联合体(Union)
12.1 union的定义与尺寸
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
// 共用体中所有的成员变量,同时只能使用一个
union MyUnion1
{
int code1;
long long code2;
float price;
bool flag;
} myUnion;
cout << "MyUnion1 size:" << sizeof(MyUnion1) << endl; // 8
struct MyStruct
{
int code1;
long long code2;
float price;
bool flag;
} myStruct{20,30,10.4,true};
cout << "MyStruct size:" << sizeof(MyStruct) << endl; // 24(字节),8的整数倍
union MyUnion2
{
int code1;
long long code2:4; // 有符号或无符号决定于变量类型是有符号还是无符号
float price;
bool flag;
} myUnion2;
cout << "MyUnion2 size:" << sizeof(MyUnion2) << endl; // 8(字节)
12.2 union是否能像struct一样初始化
不能像结构体一样初始化联合体,因为union同时只能使用一个变量
如果设置某一个变量,会覆盖union中的其他变量,比如MyUnion1中的float price是用了long long code2的低4个字节
union MyUnion1
{
int code1;
long long code2;
float price;
bool flag;
} myUnion;
myUnion.price = 10.1;
cout << "myUnion.price=" << myUnion.price << endl; // 打印10.1
myUnion.code2 =100; // 将myUnion.price覆盖
cout << "myUnion.price=" << myUnion.price << endl; // 打印的不是10.1
12.3 union中的位字段
union MyUnion2
{
int code1;
long long code2:4; // 有符号或无符号决定于变量类型是有符号还是无符号
float price; // 4位二进制最多表示15
bool flag;
} myUnion2;
myUnion2.code2 = 17; //大于15,会溢出
cout << "myUnion2.code2=" << myUnion2.code2 << endl; // 1
cout << "MyUnion2 size:" << sizeof(MyUnion2) << endl; // 8
myUnion2.code2 = 13; //小于15,不会溢出
cout << "myUnion2.code2=" << myUnion2.code2 << endl; // -3 ,为什么不是13?
cout << "MyUnion2 size:" << sizeof(MyUnion2) << endl; // 8
12.4 union的二进制存储形式
union MyUnion2
{
int code1;
long long code2:4; // 有符号或无符号决定于变量类型是有符号还是无符号
float price;
bool flag;
} myUnion2;
cout << "myUnion2.code2=" << myUnion2.code2 << endl; // -3 ,为什么不是13?
//常用的查看二进制存储形式的代码段,要记住
unsigned long long *n = (unsigned long long*)&myUnion2;
bitset<64> b(*n);
cout << b << endl; // 0000000000000......000001101
1101对应的是13,为什么打印了-3?
原因在于long long是有符号的类型,所以会认为4位的long long code2是有符号的
以补码的形式存在,最高位是符号位,补码:1101 原码:1011 对应-3
所以若在union中定义的是unsigned long long code2,就会正常输出13了
13.枚举类型
13.1 枚举类型的定义
enum color{red,yellow,green,blue}; //定义枚举类型 color
0 1 2 3
color flowerColor; //定义枚举类型变量flowerColor
13.2 枚举类型成员的默认值
enum color{red,yellow,green,blue}; //定义枚举类型 color
0 1 2 3
13.3 为枚举类型变量赋值
flowerColor = green; //为枚举类型赋值
cout << "flowerColor=" << flowerColor << endl; //打印 2
flowerColor = 1; //报错
flowerColor = (color)1; //进行强制类型转换
if(flowerColor == yellow)
{
cout << "color:yellow" << endl; // color:yellow
}
flowerColor = red + green; //报错
flowerColor = (color)(red + green);//进行强制类型转换
if(flowerColor == green)
{
cout << "flowerColor:green" << endl; // flowerColor:green
}
int value = flowerColor + 10;
cout << "value:" << value << endl; // 12
14.设置/指定枚举类型成员的值
enum Color1{RED1, GREEN1, BLUE1};
0 1 2
//引用枚举类型成员使用'::'
cout << "Color1::GREEN1=" << Color1::GREEN1 << endl; // 1
enum Color2{RED2, GREEN2 =20, BLUE2};
cout << "Color2::GREEN2=" << Color2::GREEN2 << endl; // 20
cout << "Color2::BLUE2=" << Color2::BLUE2 << endl; // 21 枚举类型成员值会顺着前一项加一
// C++允许两个或多个枚举类型成员的整型值相同
enum Color3{RED3, GREEN3 = 0, BLUE3,YELLOW3=1 };
cout << "Color3::RED3=" << Color3::RED3 << endl; // 0
cout << "Color3::GREEN3=" << Color3::GREEN3 << endl; // 0
cout << "Color3::BLUE3=" << Color3::BLUE3 << endl; // 1
cout << "Color3::YELLOW3=" << Color3::YELLOW3 << endl; // 1
Color3 color3 = Color3(1); //整型1是可以对应多个枚举类型成员的
if(color3 == Color3::BLUE3)
{
cout << "equal" << endl; // equal
}
if(color3 == Color3::YELLOW3)
{
cout << "equal" << endl; // equal
}
// 枚举类型成员的整型值是允许为负数的
enum Color4{RED4 = -2, GREEN4, BLUE4 };
cout << "Color4::RED4=" << Color4::RED4 << endl; // -2
cout << "Color4::GREEN4=" << Color4::GREEN4 << endl; // -1
cout << "Color4::BLUE4=" << Color4::BLUE4 << endl; // 0
// 枚举类型成员可以赋值字符,但存进去的是字符所对应的ASCII值,'A'对应65
enum Color5{RED5 = 'A', GREEN5, BLUE5 };
cout << "Color5::RED5=" << Color5::RED5 << endl; // 65
cout << "Color5::GREEN5=" << Color5::GREEN5 << endl; // 66
15.枚举类(enum class):C++ 11新特性
// 传统C++中,枚举成员是全局的,在不同的枚举类型中,各自的枚举成员是不能同名的
enum Color1{RED, GREEN, BLUE};
enum Color2{RED1, GREEN1, BLUE1};
Color1 color1 = Color1::RED;
if(Color1::RED == color1) //在传统的C++中,if(0 == color1)这种表达方式也可以,但可读性很差
{
cout << "color1 == Color1::RED" << endl; // color1 == Color1::RED
}
// C++11枚举类enum class,区别:允许相同的枚举成员,且不允许if(0 == color1)这种表达方式
//即,不能自动将color1转换为数值
enum class Color3{RED, GREEN,BLUE = 20};
enum class Color4{RED, GREEN,BLUE};
Color3 color3 = Color3::GREEN;
if(Color3::GREEN == color3)
{
}
cout << int(Color3::BLUE) << endl; // 需要强制类型转换后,方能输出数值
cout << Color1::BLUE << endl; //可以自动转换为数值
16.枚举类型的尺寸
16.1 计算枚举类型的尺寸
// 枚举类型的每一个成员默认对应一个int类型的值
enum Color1{RED,GREEN,BLUE};
cout << "Color1 size=" << sizeof(Color1) << endl; // 4(字节)
// 可以使用/* */ 在代码中间增加注释
// INT8_MAX 127 8位二进制最大值
// INT16_MAX 32767 16位二进制最大值
enum class Color2{RED = INT32_MAX-2,GREEN ,BLUE /*= INT32_MAX + 1:溢出,会出错*/};
cout << "Color2 size=" << sizeof(Color2) << endl; // 4(字节)
16.2 枚举类型成员对应的值的溢出
// BLUE的值超过了int的存储范围,所以会报错
enum class Color2{RED = INT32_MAX-2,GREEN ,BLUE = INT32_MAX + 1};
// 依然会报错,因为RED已经是最大,那GREEN和BLUE会按顺序加一,导致溢出
enum class Color2{RED = INT32_MAX,GREEN ,BLUE};
16.3 修改枚举类型的尺寸
enum class Color3:short{RED,GREEN,BLUE = INT16_MAX};
cout << "Color3 size=" << sizeof(Color3) << endl; // 2
enum class Color4:unsigned char{RED,GREEN,BLUE = 255}; //无符号1字节,最大255
cout << "Color4 size=" << sizeof(Color4) << endl; // 1
// C++ 11
// 有符号8位,127到-128, BLUE如果是-128的话,RED和GREEN并不会按顺序往前减一,而是从0开始
enum class Color5:int8_t{RED,GREEN,BLUE = -128};
cout << int(Color5::RED) << endl; // 0
cout << int(Color5::GREEN) << endl; // 1
17.匿名类型和类型别名
17.1 匿名类型
// MyStruct MyUnion有时可以省略
// 结构体、共用体定义
struct MyStruct
{
int code;
string name;
};
union MyUnion
{
int code;
long code1;
};
// 匿名结构体 ,后面必须跟变量
struct
{
int code;
string name;
}product;
product.name = "abc";
// 匿名共用体,后面可以不跟变量
union
{
int code;
long code1;
};
union
{
int code;
long code1;
}myCode;
// 枚举类型定义
enum enum_name{ONE,TWO,THREE}; //这种情况要是想使用枚举成员,就需要enum_name::ONE来调用
// 匿名枚举,可以不跟变量
enum {ONE,TWO,THREE};
enum {ONE,TWO,THREE} value; //这种情况枚举成员ONE,TWO,THREE是全局的,不需要'::'来调用
value = ONE;
// 即便是C++枚举类,若用匿名枚举类,那么成员ONE,TWO,THREE仍然是全局的
// 不能和其他枚举类型和匿名枚举类的成员相同
enum class {ONE,TWO,THREE} value1;
enum class abc{ONE,TWO,THREE} value1; //成员ONE,TWO,THREE变成了局部
17.2 类型别名
// typedef
typedef struct
{
int code;
string name;
}product_type;
product_type p; // product_type为类型别名,可以用来定义结构体变量
p.name = "xuz";
typedef union
{
int code;
long code1;
}myCode_type;
myCode_type code; // myCode_type 为类型别名,可以用来定义共用体变量
code.code1 = 1000;
// 对于匿名枚举类型来说,所有枚举成员(枚举值)都是全局的,不属于某个特定变量
typedef enum {ONE1,TWO1,THREE1} value_type; // value_type是一个类型,枚举类型
value_type v1 = ONE1;
typedef enum class {ONE2,TWO2,THREE2} value_type1; //value_type1可以定义枚举类变量
value_type1 v2 = ONE2;