赞
踩
“结构体”是一种构造类型,它是由若干“成员”组成的,其中的每一个成员可以是一个基本数据类型也可以是一个构造类型。
假如在程序中要使用“学生”这样一个类型,学生具有姓名、性别、年龄等属性
声明结构体使用的关键字是struct,其一般形式为:
struct 结构体名
{
成员列表
};
关键字struct表示声明结构,其后的结构体名表示该结构的类型名
注意:大括号最后面有一个分号“ ; ”,不要忘记
例如:
struct Student
{
char _name[10];
char _gender[10];
int _age;
};
使用关键字struct声明一个名为Student的结构体类型,在结构体中定义的变量是Student结构的成员。
//创建结构体模板
struct Student
{
char _name[10];
char _gender[10];
int _age;
};
//使用该模板创建3个变量stu1,stu2,stu3
struct Student stu1,stu2,stu3;
缺点就是定义变量时必须带上struct
可以使用typedef进行简写,这样在定义变量时比较简洁
//结构体模板struct Student重新命名为Stu
typedef struct Student
{
char _name[10];
char _gender[10];
int _age;
}Stu;
//使用Stu创建3个变量stu1,stu2,stu3
Stu stu1,stu2,stu3
此处使用typedef为结构体模板struct Student定义一个别名Stu
struct Student
{
char _name[10];
char _gender[10];
int _age;
}stu1,stu2,stu3;
struct
{
char _name[10];
char _gender[10];
int _age;
}stu1,stu2,stu3;
缺点:不能用该结构定义新的变量。
结构体变量名.成员名
在引用结构的成员时,可以在结构的变量名的后面加上成员运算符“ . ”和成员的名字
Stu._name = "Hanmei";
Stu._age = 15;
定义结构体数组的一般形式如下:
struct 结构体名
{
成员列表
}数组名;
struct Student
{
char _name[10];
char _gender[10];
int _age;
}stu[10];
也可以先声明结构体类型再定义结构体数组
typedef struct Student
{
char _name[10];
char _gender[10];
int _age;
}Stu;
在主函数中定义结构体数组
Stu stu[10];
结构体指针:指向结构体变量的指针
定义结构体指针的一般形式:
结构体类型* 指针名
定义一个指向struct Student结构类型的 p 指针变量如下:
struct Student* p;
使用指向结构体变量的指针访问成员有以下两种方法:
(*p).成员名;
注意:*p一定要使用括号,因为点运算符的优先级是最高的
p->成员名;
假如student为结构体变量,p为指向结构体变量的指针,则下列3种形式的效果是等价的
student.成员名;
(*p).成员名;
p->成员名;
在使用"->"引用成员时,要注意分析以下情况:
p->iGrade; //表示指向结构体变量中成员iGrade的值
p->iGrade++; //表示指向结构体变量中成员iGrade的值,使用后该值加1
++p->iGrade; //表示指向结构体变量中成员iGrade的值加1,计算后再使用
使用结构体变量作为函数的实际参数时,采取的是“值传递”,它会将结构体变量所占内存单元的内容全部顺序传递给形参,形参也必须是同类型的结构体变量
void Display(struct Student stu);
在形参的位置使用结构体变量,但是函数调用期间,形参也要占用内存单元,这种传递方式在空间和时间上开销都比较大
另外,根据函数参数传值方式,如果在函数内部修改了变量中成员的值,则改变的值不会返回到主调函数中
在传递结构体变量的指针时,只是将结构体变量的首地址进行传递,并没有将变量的副本进行传递
void Display(struct Student *stu);
实际是把实参的值赋值给行参,相当于copy。那么对行参的修改,不会影响实参的值
实际是传值的一种特殊方式,只是他传递的是地址,不是普通的赋值,那么传地址以后,实参和行参都指向同一个对象,因此对形参的修改会影响到实参
值传递:可以看到a,b的值并没有被交换
在main函数中swap(a,b)将a,b两个值传给了调用函数swap中的x,y,在swap调用函数中完成了x和y的交换,但是只是完成了x,y的交换,跟主函数中的a,b没有任何关系。这只是一次单向的传递过程,x,y是定义在函数swap中的局部变量,当函数调用结束后,它俩就over了,被残忍抛弃了(子函数的生命期为子函数开始调用到结束调用,调用结束后就主动释放了),因此它们没有渠道把交换的值传回给a,b
传地址是实参和行参都指向同一个对象,因此对形参的修改会影响到实参
struct:用户自定义数据类型,是一些变量的集合体。
union:也是一种特殊的自定义类型,也包含一系列的成员,特征是这些成员公用同一块内存空间,所以联合变量的大小,至少是最大成员的大小。
(1)struct可以存储多个成员信息,而union只能存储最后一个成员的信息;(2)struct会给每一个成员分配内存空间,而union的所有成员公用一块内存空间;
(3)union的不同成员赋值,将会对其他成员重写,而struct的不同成员赋值是互不影响的。
(1)第一个成员在偏移量为0的地址处;
(2)其他成员变量对齐到某个数字的整数倍地址处,这个数是编译器默认的对齐数与该成员大小的较小值,VS中默认是8,也可以使用#pragma pack来修改默认对齐数;
(3)结构体的总大小为最大对齐数的整数倍。
(1)联合的大小至少是最大成员的大小;
(2)当最大成员的大小不是最大对齐数的整数倍时,要对齐到最大对齐数的整数倍。
struct name1
{
char str; //1字节
short x; //2字节
int num; //4字节
};
sizeof(name1) = 8 // 1(2) + 2 + 4 = 8
struct A
{
char t:4; //4表示占一个字节的4个比特位
char k:4;
unsigned short i:8;
unsigned long m;
};
一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。
sizeof(A) = 8 //1 + 1 + 2 + 4 = 8
struct name2
{
char str;
int num;
short x;
};
sizeof(name2) = 12 // 1(4) + 4 + 2(4) = 12
struct st1
{
unsigned chara:7;/*字段a占用了一个字节的7个bit*/
unsigned charb:2;/*字段b占用了2个bit*/
unsigned charc:7;/*字段c占用了7个bit*/
}s1;
sizeof(s1) = 3 // 1 + 1 + 1 = 3
struct st2
{
unsigned inta:31;
unsigned intb:2;/*前一个整型变量只剩下1个bit,容不下2个bit,所以只能存放在下一个整型变量*/
unsigned int c:31;
}s2;
sizeof(s2) = 12 // 4 + 4 + 4 = 12
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。