自定义类型:结构体

结构体

  • 结构体的类型声明
    1.结构的声明
    2.特殊的声明
  • 结构体的自引用
  • 结构体变量的定义和初始化
  • 结构体的内存对齐
  • 结构体的传参

前言

结构体(struct)是以一系列具有相同类型或不同类型的数据构
成的集合,可以是结构的成员可以是标量、数组、指针,甚至是其他结构体结构体,使得C语言有能力描述复杂数据类型

结构体的声明


struct tag   
{
 member-list;  //结构体成员
 }variable-list; //全局变量

结构体的定义

描述一个学生
struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}; //分号不能丢
//初始化:定义变量的同时赋初值。

结构成员的类型

  • 结构的成员可以是标量、数组、指针,甚至是其他结构体
结构体的初始化
struct Stu        //类型声明
{
 char name[15];//名字
 int age;      //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Point
{
 int x;
 int y; }p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。

2.结构体成员的嵌套

struct Point p3 = {x, y};
struct Stu        //类型声明
{
 char name[15];//名字
 int age;      //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{
 int data;
 struct Point p;
 struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化
结构体成员的访问

结构变量的成员是通过点操作符(.)访问的

struct book
{
	char book_name[20];
	char name[15];
	int value;
	char call[15];
}ss1, ss2;
int main()
{
	struct book Ss1 = { "《柴哥C语言》","柴哥",198,"ADSSSSER" };
	struct book Ss2 = { "《成哥C语言》","成哥",146,"AWCCCCVR" };


	printf("%s %s %d %s\n", Ss1.book_name, Ss1.name, Ss1.value, Ss1.call);
	printf("%s %s %d %s\n", Ss2.book_name, Ss2.name, Ss2.value, Ss2.call);


	//printf("%s %s %d %s\n", Ss.book_name, Ss.name, Ss.value, Ss.call);
	return 0;
}

结构体指针访问指向变量的成员 有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。 那该如何访问成员。 如下:

struct Stu
{
 char name[20];
 int age;
};
void print(struct Stu* ps) {
 printf("name = %s   age = %d\n", (*ps).name, (*ps).age);
    //使用结构体指针访问指向对象的成员
 printf("name = %s   age = %d\n", ps->name, ps->age);
}
int main()
{
    struct Stu s = {"zhangsan", 20};
    print(&s);//结构体地址传参
    return 0; }

结构体传参的时候,要传结构体的地址。

函数传参的时候,参数是需要压栈的。
如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的
下降。

struct S 
{
 int data[1000];
 int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
 {
 printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps) 
{
 printf("%d\n", ps->num);
}
int main()
{
 print1(s);  //传结构体
 print2(&s); //传地址
 return 0; }
结构体的内存对齐在这里插入图片描述

struct S1
{
	char b1;
	char b2;
	int bur;
};

struct S2
{
	char b1;
	int bur;
	char b2;
};

int main()
{

	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));

	return 0;
}

在这里插入图片描述

struct S1
{
	char b1;
	char b2;
	int bur;
};

struct S2
{
	char b1;
	int bur;
	char b2;
};
#include <stddef.h>
//offsetof
int main()
{
	
	printf("%d\n", offsetof(struct S1,b1));
	printf("%d\n", offsetof(struct S1, b2));
	printf("%d\n\n", offsetof(struct S1, bur));

	printf("%d\n", offsetof(struct S2, b1));
	printf("%d\n", offsetof(struct S2, b2));
	printf("%d\n", offsetof(struct S2, bur));
	return 0;
}

在这里插入图片描述

S1和S2类型的成员一模一样,但是S1和S2所占空间的大小有了一些区别。

首先得掌握结构体的对齐规则:

  1. 第一个成员在与结构体变量偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
    对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
    VS中默认的值为8
  3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
    体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值