数组
一维数组------------------------------------------
形式:
类型 数组名 [常量表达式]
注意:
数组长度必须确定,下标由0开始
初始化:
- 全部初始化(可不必标明数组长度)
- 部分初始化(其余以0赋值上去)
说明:
标准 C++ 中,一旦你在数组定义时就对其使用 '{ }' 初始化,不论 '{' 与 '}' 之间的数值是多少(当然给比数组的上界小了)编译器会自动给你没有初始化的项用 0 初始化.与整型数组初始化相似,只是 int 使用的默认值为 0 ,而char型使用的是 '\0' .指针数组的初始化与以上初始化方式相同,使用默认值是 NULL ,而且初始化时可以使用值为 0 或 NULL
例子:
// 例1 -- 部分初始化
int a[5] = {1,0,3}; // 部分初始化即 a[0]=1, a[1]=0, a[2]=3,为初始化的值都为0,即 a[3]=0, a[4]=0
int b[5]; //定义有五个元素的数组,没有初始化任何元素,元素都为 0
// 例2 -- 全部初始化
int a[5] = {1,2,3,4,5};
int b[] = {1,2,3,4,5}; //等价于上面那个数组,数组长度为{}里面的元素个数但是出现
int c[]; //错误, int 数组名[] 时候后面一定要初始化全部元素否则报错
// 例3 -- 调用数组元素
int a[5] ;
a[0] = 5; //将 a 这个数组的第一个元素即 a[0] 赋值为5
二维数组------------------------------------------
形式:
类型 数组名[常量表达式(行)][常量表达式(列)]
初始化:
- 分行初始化
- 全员初始化
- 部分初始化
例子:
// 例1 -- 分行初始化
int a[2][3]={{1,2,3},{4,5,6}};
// 例2 -- 全员初始化
int a[2][3]={1,2,3,4,5,6};
// 例3 -- 部分初始化
int a[2][3]={{1},{4,6}};
// 例4 -- 调用数组成员
int a[2][3] ;
a[0][0] = 9 ; //将数组 a 第一行第一列的这个元素即 a[0][0] 赋值为9;
内存模型:
二维数组元素在内存中顺序排放,排列顺序是按行存放.即先顺序存放第一行的数组元素,然后存放第二行的数组元素,然後每行的數組元素是按重大到小的順序排列,依此类推
例子:
void main()
{
int a[2][3]={{0,1,2},{5,6,7}};
cout<<endl;
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
cout<<"地址为 "<<(a+i)<<" 的a["<<i<<"] 值为"<<*(a+i)<<endl;
cout<<"地址为 "<<*(a+i)+j<<" 的a["<<i<<"]["<<j<<"] 值为: "<<*(*(a+i)+j)<<endl<<endl;
}
}
system("pause");
}
輸出結果:
其數組內存模型為:
字符数组------------------------------------------
形式:
char 数组名[常量表达式];
初始化:
- char 数组名[常量表达式] = {'字符', '字符', '字符', ...};
- char 数组名[常量表达式] = {“l字符串”};
- char 数组名[常量表达式] = “字符串”;
注意:
- 字符数组须初始化,且长度不大于数组长度,未初始化的元素以'\0'填充
- 字符数组以'\0'结束,但字符数组中不必包含'\0'系统会自动加一个'\0'输出时也不含'\0'
- 如果一个字符数组包含两个以上'\0',则遇到第一个'\0'时就停止输出
- 在定义char a[]=“I'm happy”或char a[]={“I'm happy”}时,字符长为10而不是9,因为把'\0'算入长度中去
字符串面值的连接:
- 两个相邻的仅由空格,制表符,换行符的字符串的面值(或宽字符串面值),可连接成一个新的字符面值
- 若连接字符串面值和宽字符面值,其结果是未定义的
例子:
// 例1 -- 全部初始化初始化
char a[4]={'I','a','m','t'};
char b[5]={"lamt"}; //这里的数组长度为 5 ,而不是4,因为字符串结尾需要一个标志结尾的字符 '\0' ,
//所以长度是 5 也就是数组最小要长度为 5 ,而不是 4
char c[5]="lamt"; //同上
// 例2 -- 部分初始化初始化
char a[9]={'I','a','m','t'};
char b[9]={"lamt"};
char c[9]="lamt";
// 例3 -- 调用数组元素
char a[5];
a[0] = 'b' ; //这里将数组 a 的第一个元素即 a[0] 赋值为字符 'b'
a[1] = 63; //这里将数组 a 的第二个元素即 a[1] 赋值为ASII码值为63的这个字符值
共用体
格式:
union 公用体名{
成员声明;
};
说明:
是一种数据格式,它能够存储,但只能同时存储一种类型,也就是说,结构体可以同时存储int,long与double类型的,某一时刻共用体只能存储int,long与double中的一种类型,共用体语法与结构体相似但含义不同,共用体在当数据项使用两种或更多种格式(但数据项不会同时使用一种以上格式)时可以节约存储空间
例子:
union U_v{
short int a;
short int b;
int c;
};
struct S_v{
short int a;
short int b;
int c;
};
void main()
{
U_v a;
a.a = 0;
a.b = 0;
a.c = 0; //初始化成员变量
cout<<"共有体的长度为 "<<sizeof(a)<<endl;
a.c = 9;
cout<<"修改共用体中的变量 c = 9 "<<endl;
cout<<"共用体的变量 a , b , c 值为: "<<a.a<<", "<<a.b<<", "<<a.c<<endl;
a.b = 6;
cout<<"修改共用体中的变量 b = 6 "<<endl;
cout<<"共用体的变量 a , b , c 值为: "<<a.a<<", "<<a.b<<", "<<a.c<<endl;
a.a = 5;
cout<<"修改共用体中的变量 a = 5 "<<endl;
cout<<"共用体的变量 a , b , c 值为: "<<a.a<<", "<<a.b<<", "<<a.c<<endl<<endl;
//可以看出变量共享同一个内存,所以改一个其他的内容也变了
S_v b;
b.a = 0;
b.b = 0;
b.c = 0; //初始化成员变量
cout<<"结构体的长度为 "<<sizeof(b)<<endl;
b.c = 9;
cout<<"修改结构体中的变量 c = 9 "<<endl;
cout<<"结构体的变量 a , b , c 值为: "<<b.a<<", "<<b.b<<", "<<b.c<<endl;
b.b = 6;
cout<<"修改结构体中的变量 b = 6 "<<endl;
cout<<"结构体的变量 a , b , c 值为: "<<b.a<<", "<<b.b<<", "<<b.c<<endl;
b.a = 5;
cout<<"修改结构体中的变量 a = 5 "<<endl;
cout<<"结构体的变量 a , b , c 值为: "<<b.a<<", "<<b.b<<", "<<b.c<<endl;
//可以看出变量有各自的内存,修改了某个变量,它对其他变量是没有任何影响的
system("pause");
}
输出结果:
枚举
格式
enum 枚举名 {
枚举常量/枚举成员
};
说明:
- 在默认情况下red,orange,yellow它们对应的整数为0 ~2
- 把非enum值赋给enum变量被视为错误
- 枚举量是整型,可以被提升为int型,但int型不能被转换为枚举类型
- 可以为一个,多个枚举成员赋初值,初始化枚举成员的值必须为一个常量表达式,没有赋初值的枚举成员的值为前一个枚举成员的值加一
- 不能改变枚举成员的值,枚举成员本身就是一个常量表达式
- 枚举类型对象初始化或赋值,只能通过其枚举成员或者同一枚举型的的对象来进行
例子:
enum weekday{ sun,mou,tue=7,wed,thu,fri,sat };
void main(void)
{
enum weekday a,b,c,d,e;
a = sun;
b = (weekday)1;
c = mou;
d = tue;
e = wed;
cout<<"the value a is "<<a<<endl;
cout<<"the value b is "<<b<<endl;
cout<<"the value c is "<<c<<endl;
cout<<"the value d is "<<d<<endl;
cout<<"the value e is "<<e<<endl;
system("pause");
}
/*****************************************
输出结果
the value a is 0
the value b is 1
the value c is 1
the value d is 7
the value e is 8
请按任意键继续. . .
*****************************************/
解释:
在 weekday 其各个成员变量的值是 sun = 0 , mou = 1 , tue = 7 , wed = 8 , thu = 9 , thu = 10 , fri = 11 , sat = 12
在枚举成员中开头成员 sun 因为没有显示的给与其赋值所以为默认为 0 ,如果有显示赋值的话 sun 的值便为其赋值的值, 但枚举成员 tue 有显示的赋值为 7 ,所以tue = 7 , 其他的没有给定显示赋值的成员,值为前一个成员值加 1
由上我们终结出如何得知枚举变量成员中的值我们可以分三个步骤来看:
-
- 先看枚举成员变量中有显示赋值的成员( 就是上个例子中的 tue 变量成员)
- 接着看枚举成员的第一个成员常量,如果其有被显示赋值它的值变为其赋值的值, 如果没有它的值为 0
- 再看即不是第一个也没有显示赋值的枚举成员,它们的值变等于前一个枚举成员值加 1
段字位
定义:
由signed int或unsigned int中一组相邻的位,段字位由一个 结构声明建立,该结构声明为每个字段提供标签,并决定字段宽度
例:
struct {unsigned int aufd:4;unsigned int itals:2} prnt;
说明
①变量prnt被存放在一个int大小的存储空间里,但只有6位被使用
②带有位字段的结构允许在单个单元内存储多项设置
③位字段赋值要保证没有超过字符的容量
④不允许一个字段跨越两个unsigned的边界
例子:
struct Bit
{
char b8: 1;//低位
char b7: 1;
char b6: 1;
char b5: 1;
char b4: 1;
char b3: 1;
char b2: 1;
char b1: 1;//高位
};
struct Not_Bit{
char b8;
char b7;
char b6;
char b5;
char b4;
char b3;
char b2;
char b1;
};
void main(void)
{
unsigned char *p = NULL;
Bit B;
Not_Bit n_B;
cout<<"this is Bit"<<endl;
B.b1 = 1; B.b2 = 1; B.b3 = 1; B.b4 = 1; B.b5 = 1; B.b6 = 1; B.b7 = 1; B.b8 = 1;
//对Bit结构体赋值
p = (unsigned char *)&B;
cout<<"把 Bit 转化成 unsigned char 类型然后看看其值为: "<<(int)(*p)<<endl;
B.b1 = 0; B.b2 = 0; B.b3 = 0; B.b4 = 0; B.b5 = 0; B.b6 = 0; B.b7 = 0; B.b8 = 0;
//对Bit结构体赋值
p = (unsigned char *)&B;
cout<<"把 Bit 转化成 unsigned char 类型然后看看其值为: "<<(int)(*p)<<endl;
B.b1 = 0; B.b2 = 0; B.b3 = 0; B.b4 = 0; B.b5 = 1; B.b6 = 1; B.b7 = 0; B.b8 = 1;
//对Bit结构体赋值
p = (unsigned char *)&B;
cout<<"把 Bit 转化成 unsigned char 类型然后看看其值为: "<<(int)(*p)<<endl;
B.b1 = 1; B.b2 = 2; B.b3 = 3; B.b4 = 4; B.b5 = 5; B.b6 = 6; B.b7 = 7; B.b8 = 8;
//对Bit结构体赋值
//由于 B 中成员变量存放的都是字节,所以在赋给它们超过其容量时候会进行截取,即舍弃前面超出范围的部分
p = (unsigned char *)&B;
cout<<"把 Bit 转化成 unsigned char 类型然后看看其值为: "<<(int)(*p)<<endl<<endl;
cout<<"this is Not_Bit"<<endl;
n_B.b1 = 1; n_B.b2 = 1; n_B.b3 = 1; n_B.b4 = 1; n_B.b5 = 1; n_B.b6 = 1; n_B.b7 = 0; n_B.b8 = 1;
//对NotBit结构体赋值
p = (unsigned char *)&n_B;
cout<<"把 Not_Bit 转化成 unsigned char 类型然后看看其值为: "<<(int)(*p)<<endl;
n_B.b1 = 0; n_B.b2 = 0; n_B.b3 = 0; n_B.b4 = 0; n_B.b5 = 0; n_B.b6 = 0; n_B.b7 = 0; n_B.b8 = 0;
//对NotBit结构体赋值
p = (unsigned char *)&n_B;
cout<<"把 Not_Bit 转化成 unsigned char 类型然后看看其值为: "<<(int)(*p)<<endl;
n_B.b1 = 0; n_B.b2 = 0; n_B.b3 = 0; n_B.b4 = 0; n_B.b5 = 1; n_B.b6 = 1; n_B.b7 = 0; n_B.b8 = 1;
//对NotBit结构体赋值
p = (unsigned char *)&n_B;
cout<<"把 Not_Bit 转化成 unsigned char 类型然后看看其值为: "<<(int)(*p)<<endl;
n_B.b1 = 0; n_B.b2 = 2; n_B.b3 = 3; n_B.b4 = 4; n_B.b5 = 5; n_B.b6 = 6; n_B.b7 = 7; n_B.b8 = 8;
//对NotBit结构体赋值
//由于 n_B 中成员变量存放的都是字符型变量,所以在赋给它们的值都未超其容量,即没有发生舍弃
p = (unsigned char *)&n_B;
cout<<"把 Not_Bit 转化成 unsigned char 类型然后看看其值为: "<<(int)(*p)<<endl<<endl;
system("pause");
}
输出结果:
分析:
让我来看看 B 与 n_B 两个变量的内存分配的模型吧,其中每个小红框框代表一个字节位
那么现在我们在看看代码中的的两个句
//--------------------------------------------------------------------------------
//先看看关于 B 变量
p = (unsigned char *)&B;
//那么 B 这个结构体变量只有 8 字节位刚好是一个 unsigned char 变量的内存大小所以 B 在发生强制转换的时候没有丢失数据
//--------------------------------------------------------------------------------
//再来看看关于 n_B 变量
p = (unsigned char *)&n_B;
//此时 n_B 变量强制转换为 unsigned char 变量,我们在看看那上面 n_B 的内存分配,明显它有 8 个字符变量成员,所以它所占的内存是 64 字节位
//那么它转换后的的内存模型就剩下 8 字节位(既成员变量 b8 ),丢失 n_B 余下的 56 字节(即成员变量 b7 到 b1)
//所以在那些输出结构其实都是变量 b8 的数据内容