当前位置:   article > 正文

【C语言】1. 结构体struct(结构体概念、结构体指针、结构体作为函数参数、传值与传地址、内存对齐(struct与union))_c语言struct函数

c语言struct函数

1. 结构体struct

1.1 结构体类型的概念

“结构体”是一种构造类型,它是由若干“成员”组成的,其中的每一个成员可以是一个基本数据类型也可以是一个构造类型。
假如在程序中要使用“学生”这样一个类型,学生具有姓名、性别、年龄等属性
声明结构体使用的关键字是struct,其一般形式为:

struct 结构体名
{
	成员列表
};
  • 1
  • 2
  • 3
  • 4

关键字struct表示声明结构,其后的结构体名表示该结构的类型名
注意:大括号最后面有一个分号“ ; ”,不要忘记
例如:

struct Student
{
	char _name[10];
	char _gender[10];
	int _age;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用关键字struct声明一个名为Student的结构体类型,在结构体中定义的变量是Student结构的成员。

1.2 结构体变量的定义

1.2.1 声明结构体类型,再定义变量(最常用)

//创建结构体模板
struct Student
{
	char _name[10];
	char _gender[10];
	int _age;
};
//使用该模板创建3个变量stu1,stu2,stu3
struct Student stu1,stu2,stu3;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

缺点就是定义变量时必须带上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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

此处使用typedef为结构体模板struct Student定义一个别名Stu

1.2.2 在声明结构体类型时,定义变量

struct Student
{
	char _name[10];
	char _gender[10];
	int _age;
}stu1,stu2,stu3;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

1.2.3 直接定义结构体类型变量

struct 
{
	char _name[10];
	char _gender[10];
	int _age;
}stu1,stu2,stu3;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

缺点:不能用该结构定义新的变量。

1.3 结构体变量的引用

结构体变量名.成员名
  • 1

在引用结构的成员时,可以在结构的变量名的后面加上成员运算符“ . ”和成员的名字

Stu._name = "Hanmei";
Stu._age = 15;
  • 1
  • 2

2. 结构体数组

定义结构体数组的一般形式如下:

struct 结构体名
{
	成员列表
}数组名;
  • 1
  • 2
  • 3
  • 4
struct Student
{
	char _name[10];
	char _gender[10];
	int _age;
}stu[10];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

也可以先声明结构体类型再定义结构体数组

typedef struct Student
{
	char _name[10];
	char _gender[10];
	int _age;
}Stu;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在主函数中定义结构体数组

Stu stu[10];
  • 1

3. 结构体指针

3.1 概念

结构体指针:指向结构体变量的指针
定义结构体指针的一般形式:

结构体类型* 指针名
  • 1

定义一个指向struct Student结构类型的 p 指针变量如下:

struct Student* p;
  • 1

使用指向结构体变量的指针访问成员有以下两种方法:

3.2 第一种方法是使用点运算符引用结构成员

(*p).成员名;
  • 1

注意:*p一定要使用括号,因为点运算符的优先级是最高的

3.3 第二种方法是指向运算符引用结构成员

p->成员名;
  • 1

假如student为结构体变量,p为指向结构体变量的指针,则下列3种形式的效果是等价的

student.成员名;
(*p).成员名;
p->成员名;
  • 1
  • 2
  • 3

在使用"->"引用成员时,要注意分析以下情况:
p->iGrade; //表示指向结构体变量中成员iGrade的值
p->iGrade++; //表示指向结构体变量中成员iGrade的值,使用后该值加1
++p->iGrade; //表示指向结构体变量中成员iGrade的值加1,计算后再使用

4. 结构体作为函数参数

4.1 使用结构体变量作为函数参数

使用结构体变量作为函数的实际参数时,采取的是“值传递”,它会将结构体变量所占内存单元的内容全部顺序传递给形参,形参也必须是同类型的结构体变量

void Display(struct Student stu);
  • 1

在形参的位置使用结构体变量,但是函数调用期间,形参也要占用内存单元,这种传递方式在空间和时间上开销都比较大
另外,根据函数参数传值方式,如果在函数内部修改了变量中成员的值,则改变的值不会返回到主调函数中

4.2 使用指向结构体变量的指针作为函数参数

在传递结构体变量的指针时,只是将结构体变量的首地址进行传递,并没有将变量的副本进行传递

void Display(struct Student *stu);
  • 1

5. 传值与传地址

5.1 传值

实际是把实参的值赋值给行参,相当于copy。那么对行参的修改,不会影响实参的值

5.2 传地址

实际是传值的一种特殊方式,只是他传递的是地址,不是普通的赋值,那么传地址以后,实参和行参都指向同一个对象,因此对形参的修改会影响到实参

5.3 传值举例

在这里插入图片描述
在这里插入图片描述
值传递:可以看到a,b的值并没有被交换
在main函数中swap(a,b)将a,b两个值传给了调用函数swap中的x,y,在swap调用函数中完成了x和y的交换,但是只是完成了x,y的交换,跟主函数中的a,b没有任何关系。这只是一次单向的传递过程,x,y是定义在函数swap中的局部变量,当函数调用结束后,它俩就over了,被残忍抛弃了(子函数的生命期为子函数开始调用到结束调用,调用结束后就主动释放了),因此它们没有渠道把交换的值传回给a,b

5.4 传地址举例

在这里插入图片描述
在这里插入图片描述
传地址是实参和行参都指向同一个对象,因此对形参的修改会影响到实参

6. 内存对齐(struct 与 union)

6.1 struct 与 union区别

struct:用户自定义数据类型,是一些变量的集合体。
union:也是一种特殊的自定义类型,也包含一系列的成员,特征是这些成员公用同一块内存空间,所以联合变量的大小,至少是最大成员的大小。
(1)struct可以存储多个成员信息,而union只能存储最后一个成员的信息;(2)struct会给每一个成员分配内存空间,而union的所有成员公用一块内存空间;
(3)union的不同成员赋值,将会对其他成员重写,而struct的不同成员赋值是互不影响的。

6.2 结构体内存对齐

(1)第一个成员在偏移量为0的地址处;
(2)其他成员变量对齐到某个数字的整数倍地址处,这个数是编译器默认的对齐数与该成员大小的较小值,VS中默认是8,也可以使用#pragma pack来修改默认对齐数;
(3)结构体的总大小为最大对齐数的整数倍。

6.3 联合体内存对齐

(1)联合的大小至少是最大成员的大小;
(2)当最大成员的大小不是最大对齐数的整数倍时,要对齐到最大对齐数的整数倍。

6.4 类型所占字节数

在这里插入图片描述

6.5 内存对齐示例

示例1

struct name1
{
	char str;  //1字节
	short x;   //2字节
	int num;   //4字节
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
sizeof(name1) = 8  // 1(2) + 2 + 4 = 8
  • 1

示例2

struct A
{
char t:4; //4表示占一个字节的4个比特位
char k:4;
unsigned short i:8;
unsigned long m;
}; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。

sizeof(A) = 8   //1 + 1 + 2 + 4 = 8
  • 1

示例3

struct name2
{
	char str;
	int num;
	short x;
}; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
sizeof(name2) = 12   // 1(4) + 4 + 2(4) = 12
  • 1

示例4

struct st1
{
	unsigned chara:7;/*字段a占用了一个字节的7个bit*/

	unsigned charb:2;/*字段b占用了2个bit*/

	unsigned charc:7;/*字段c占用了7个bit*/
}s1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
sizeof(s1) = 3  // 1 + 1 + 1 = 3
  • 1

示例5

struct st2
{
	unsigned inta:31;

	unsigned intb:2;/*前一个整型变量只剩下1个bit,容不下2个bit,所以只能存放在下一个整型变量*/

	unsigned int c:31;
}s2;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
sizeof(s2) = 12   // 4 + 4 + 4 = 12
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/142831
推荐阅读
  

闽ICP备14008679号