C语言之结构体


前言

       结构体是C语言中一种非常重要的数据类型,它允许用户将不同类型的数据组合在一起,形成一个新的数据类型。结构体可以用来表示现实世界中的实体或者抽象的概念,使得程序的设计更加灵活和可读性更强。通过结构体,我们可以将相关的数据组织在一起,并通过一个名称来引用这些数据,方便管理和操作。在C语言中,结构体由一组不同类型的数据成员组成,可以通过.来访问结构体中的各个成员,提供了一种灵活且强大的数据组织方式。在接下来的讲解中,我们将深入探讨结构体的定义、声明、初始化和使用方法,帮助您更好地理解和应用这一重要的数据类型。


一、结构体定义

        结构体是一种用户自定义的数据类型,用于封装不同数据类型的成员变量。结构体的定义通常包括结构体名称和成员变量列表。在C语言中,结构体的定义示例如下:

#include <stdio.h>
int main ()
{ 
	//*创建结构体变量*/
	typedef enum card_type {SFZ,JSZ,XSZ} CARD_TYPE;

	//宏常量
    #define MAN 'm'
    #define WOMAN 'w'

	/*创建结构体变量*/
	 struct stu_info
	{
		int stuNum;
		CARD_TYPE cardType;//证件类型
		char cardNum[30];
		char stuName[20];
		char sex;
	}s1,s2; 

    //赋初值
	 struct stu_info s3 = {2,JSZ,"2112123213","张三",MAN},
		 s4 = {.sex=WOMAN,.stuNum=3,.stuName="李四"};

	/*存取结构体成员值 用.操作符*/
	 scanf("%d%d%s%s %c",&s1.stuNum,&s1.cardType,s1.cardNum,s1.stuName,&s1.sex);
	/* scanf_s("%d%d%s%s %c",&s1.stuNum,&s1.cardType,
						s1.cardNum,30,s1.stuName,20,
						&s1.sex,1);*/

	typedef struct aa
	 {
		 int stu;
		 char sex;
		char  stuName[30];
	 }student;

	return 0;
}

二、结构体数组

        结构体数组的作用在于可以同时存储多个具有相似结构的数据,并以数组的形式进行操作和管理。结构体数组可以方便地对一组相关数据进行组织和处理,使得代码更加模块化和易于维护。通过结构体数组,可以将多个实例化的结构体对象存储在一个数组中,然后通过循环或索引来访问和操作每个结构体对象的成员变量。

结构体数组的使用场景包括但不限于:

  1. 存储多个学生的信息,如姓名、年龄、学号等。
  2. 管理多个员工的工资、职位等信息。
  3. 表示多个几何形状的坐标、颜色等属性。
  4. 在图形界面编程中,存储多个控件的位置、大小等属性。
  5. 维护游戏中的多个角色或道具的属性。

通过结构体数组,可以更有效地组织和管理这些相关数据,提高代码的可读性和可维护性。

#include <stdio.h>
/*定义一个结构体*/
//书架的书
struct book
{
	char name[30];
	char writer[20];
	double price;
	int year;
};
typedef struct book BOOK;
int main ()
{
	
	/*创建结构体数组变量*/
	BOOK b1;
	BOOK books[4]= { {"C语言从入门到放弃","谭浩强",20.8,1999},
						{"毛泽东选集","毛泽东",54.8,2000},
						{"三体","刘慈欣",65.8,2000},
						{"活着","余华",30.5,2000} };

	/*为结构体成员赋值 用.操作符*/
	/*for (int i=0;i<4;i++)
	{
		printf("%-30s %-20s %7.6f %2d\n",books[i].name,books[i].writer,books[i].price,books[i].year);
	}*/


    //排序:根据书的年份,若年份相同则根据价格
	for (int suo=0;suo<4-1;suo++)
	{
		for (int bi=suo+1;bi<4;bi++)
		{
			if (books[suo].year>books[bi].year|| books[suo].year == books[bi].year&& books[suo].price< books[bi].price)
			{
				BOOK t;
				t = books[suo];
				books[suo] = books[bi];
				books[bi] = t;

			}
		}
	}

    //打印
	for (int i = 0; i < 4; i++)
	{
		printf("%-30s %-20s %7.6f %2d\n", books[i].name, books[i].writer, books[i].price, books[i].year);
	}
	return 0;
}

三、结构体指针

        结构体指针可以使用指针来引用结构体变量,在函数参数传递和动态内存分配时特别有用。

#include <stdio.h>
#include<string.h>
/*定义一个结构体*/
typedef struct book
{
	char name[30];
	char writer[20];
	double price;
	int year;
}BOOK,*P_book;

//typedef BOOK* P_book  ;

int main()
{
	
	/*创建结构体指针变量*/
	BOOK books[4] = { {"C语言从入门到放弃","谭浩强",20.8,1999},
					{"毛泽东选集","毛泽东",54.8,2000},
					{"三体","刘慈欣",65.8,2000},
					{"活着","余华",30.5,2000} };
	struct book* p1 = &books[1];
	BOOK* p2 = books;
	P_book p3 = books+3;

	/*使用指针操作结构体成员 
	  
	 方式一:  (*指针).成员
	 方式二:  指针 -> 成员	 
	 */

	(*p1).price =10 ;
	p2->year = 2000;
	strcpy(p3->name,"huozhe");

	return 0;
}

 四、结构体对齐

        结构体对齐是编程中的一个概念,用于内存对齐的优化。在C语言中,结构体内部的成员会按照特定的规则进行对齐,以便更有效地存取内存。在结构体定义中,成员的对齐规则是由编译器自动处理的。

        结构体对齐的规则通常是按照结构体成员中最大的数据类型进行对齐,确保结构体的起始地址是成员中最大数据类型的整数倍。这样可以避免因为数据存取的地址不对齐导致的性能问题

        在一些特殊情况下,可以使用编译器指令或者预处理器指令来指定结构体的对齐方式,以达到特定的优化目的。特别是在需要优化内存访问速度和节省内存空间的情况下,需要注意结构体内部成员的对齐规则。

#include <stdio.h>
 
struct AA 
{
	int a; 
	short c; 
	char b; 
}  ;

struct HH  
{
	int a; 
	short c; 
	char b; 
	short d; 
	char e; 
	short f;
}  ;

struct HH2
{
	int a; 
	short c; 
	short d; 
	char e; 
	char b; 
	short f;
}  ;

struct FF1
{
	char a[5]; 
	char *e;
}  ;


int main  ()
{
	//测试不同结构体的空间大小
	printf("%d\n",sizeof(struct FF1));
  

	return 0;
}

 五、结构体位域使用

        结构体位域(Bit-fields in Structures)是一种在C语言中用来对结构体成员进行位级别的控制的技本。通过结构体位域,我们可以精确地控制结构体成员所占用的位数和存储顺序,以便节省内存空间

        在定义结构体时,可以使用位域来指定每个成员变量占用的位数,例如:

struct {
    unsigned int flag1 : 1;  // 1位
    unsigned int flag2 : 2;  // 2位
    unsigned int flag3 : 5;  // 5位
} status;

        在上面的例子中,结构体status有三个成员变量,分别为flag1flag2flag3,它们分别占用1位、2位和5位。在内存中,这几个位域会依次排列,占用总共8位(1+2+5)。

        需要注意的是,使用位域要注意位域在内存中的布局可能受到编译器的实现限制,不同编译器可能对位域的存储顺序有所不同。此外,位域的位数不能超过成员类型的位数,否则行为是未定义的。

        结构体位域通常用于对设备寄存器、位操作等有特殊需求的场景,能够更加灵活地管理和操作位级数据。

#include <stdio.h>
/*定义一个结构体*/
//结构体位域 应用于嵌入式领域居多
typedef struct  
{
	 int a:2;//a变量占两个位的存储空间 但int会分配4个字节。
	 int b:8;
	 int c:2;
	 int :0;//断开
	 int d:2;

}  TT;
 
int main()
{
	TT t ;
	t.a = 8;
	printf("%d\n",t.a);
	//printf("%d\n",sizeof(TT));

	return 0;
}

 六、结构体的嵌套

        结构体的嵌套是指在一个结构体中使用另一个结构体作为其成员。这种嵌套可以使数据结构更加灵活,可以构建复杂的数据模型。具体来说,结构体的嵌套可以分为两种方式:嵌套结构体作为成员变量和嵌套结构体作为指针。

嵌套结构体作为成员变量

#include <stdio.h>
 
typedef struct book
{
	int price;
	char* name;
} Book;
/*typedef struct
{
	int age;
	char *name;
	Book book;
}  Student;*/
typedef struct
{
	int age;
	char* name;
	struct 
	{
		int price;
		char* name;
	} book;
}  Student;


//适合表达:包含的关系
struct Head
{
	struct Eye
	{
		double dushu;
		int color;
		struct
		{
			int a, b, c;
		} shiwangmo;
	} left, right;
};

int main ()
{
	Student s={  20,"张三",{12,"如来神掌"} };
	struct Head head;
	printf("书名:%s\n",s.book.name);//得到嵌套结构体内的成员,继续  .  运算
	printf("价格:%d\n",s.book.price);
	return 0;
}

 嵌套结构体作为指针

#include <stdio.h>

struct Address {
    char city[50];
    char street[50];
};

struct Person {
    char name[50];
    int age;
    struct Address *address;
};

int main() {
    struct Address address1 = {"New York", "Broadway"};
    struct Person person1 = {"Alice", 25, &address1};
    printf("Person's name: %s\n", person1.name);
    printf("Person's age: %d\n", person1.age);
    printf("Person's city: %s\n", person1.address->city);
    printf("Person's street: %s\n", person1.address->street);

    return 0;
}


总结

        结构体在编程中是一种非常重要的数据结构,它可以用来组合不同类型的数据成为一个新的数据类型。结构体可以包含多个不同类型的成员变量,每个成员变量可以有自己的名称和数据类型。

        通过结构体,我们可以更方便地对相关的数据进行组织和管理,提高代码的可读性和维护性。在C语言中,结构体的定义使用关键字struct,并且可以在结构体定义中声明多个成员变量

        结构体的使用可以帮助我们实现更复杂的数据结构,比如链表、树等。此外,结构体还可以作为参数传递给函数,从而实现更灵活的数据处理操作。

        总的来说,结构体是一种非常有用的数据类型,能够帮助我们更好地组织和管理数据,提高代码的可维护性和可扩展性。在实际编程中,结构体的灵活运用可以大大简化代码的编写过程,让程序更加清晰易懂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小辉同志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值