C 结构体
C 数组允许定义可存储相同类型数据项的变量,结构是 C 编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。
结构体中的数据成员可以是基本数据类型(如 int、float、char 等),也可以是其他结构体类型、指针类型等。
结构用于表示一条记录,假设您想要跟踪图书馆中书本的动态,您可能需要跟踪每本书的下列属性:
- Title
- Author
- Subject
- Book ID
定义结构
结构体定义由关键字 struct 和结构体名组成,结构体名可以根据需要自行定义。
struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:
member-list
member-list
member-list
...
} variable-list ;
tag 是结构体标签。
member-list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义。
variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。下面是声明 Book 结构的方式:
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。以下为实例:
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct
{
int a;
char b;
double c;
} s1;
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{
int a;
char b;
double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;
//也可以用typedef创建新类型
typedef struct
{
int a;
char b;
double c;
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;
在上面的声明中,第一个和第二声明被编译器当作两个完全不同的类型,即使他们的成员列表是一样的,如果令 t3=&s1,则是非法的。
结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。
struct COMPLEX
{
char string[100];
struct SIMPLE a;
};
//此结构体的声明包含了指向自己类型的指针
struct NODE
{
char string[100];
struct NODE *next_node;
};
如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明,如下所示:
//结构体A中包含指向结构体B的指针
struct A
{
struct B *partner;
//other members;
};
//结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明
struct B
{
struct A *partner;
//other members;
};
结构体变量的初始化
和其它类型变量一样,对结构体变量可以在定义时指定初始值。
实例
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book = {"C 语言", "RUNOOB", "编程语言", 123456};
int main()
{
printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}
执行输出结果为:
title : C 语言 author: RUNOOB subject: 编程语言 book_id: 123456
访问结构成员
为了访问结构的成员,我们使用成员访问运算符(.)。成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个句号。您可以使用 struct 关键字来定义结构类型的变量。下面的实例演示了结构的用法:
实例
#include <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main( )
{
struct Books Book1; /* 声明 Book1,类型为 Books */
struct Books Book2; /* 声明 Book2,类型为 Books */
/* Book1 详述 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Book2 详述 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 输出 Book1 信息 */
printf( "Book 1 title : %s\n", Book1.title);
printf( "Book 1 author : %s\n", Book1.author);
printf( "Book 1 subject : %s\n", Book1.subject);
printf( "Book 1 book_id : %d\n", Book1.book_id);
/* 输出 Book2 信息 */
printf( "Book 2 title : %s\n", Book2.title);
printf( "Book 2 author : %s\n", Book2.author);
printf( "Book 2 subject : %s\n", Book2.subject);
printf( "Book 2 book_id : %d\n", Book2.book_id);
return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Book 1 title : C Programming Book 1 author : Nuha Ali Book 1 subject : C Programming Tutorial Book 1 book_id : 6495407 Book 2 title : Telecom Billing Book 2 author : Zara Ali Book 2 subject : Telecom Billing Tutorial Book 2 book_id : 6495700
结构作为函数参数
您可以把结构作为函数参数,传参方式与其他类型的变量或指针类似。您可以使用上面实例中的方式来访问结构变量:
实例
#include <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* 函数声明 */
void printBook( struct Books book );
int main( )
{
struct Books Book1; /* 声明 Book1,类型为 Books */
struct Books Book2; /* 声明 Book2,类型为 Books */
/* Book1 详述 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Book2 详述 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 输出 Book1 信息 */
printBook( Book1 );
/* 输出 Book2 信息 */
printBook( Book2 );
return 0;
}
void printBook( struct Books book )
{
printf( "Book title : %s\n", book.title);
printf( "Book author : %s\n", book.author);
printf( "Book subject : %s\n", book.subject);
printf( "Book book_id : %d\n", book.book_id);
}
当上面的代码被编译和执行时,它会产生下列结果:
Book title : C Programming Book author : Nuha Ali Book subject : C Programming Tutorial Book book_id : 6495407 Book title : Telecom Billing Book author : Zara Ali Book subject : Telecom Billing Tutorial Book book_id : 6495700
指向结构的指针
您可以定义指向结构的指针,方式与定义指向其他类型变量的指针相似,如下所示:
struct Books *struct_pointer;
现在,您可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:
struct_pointer = &Book1;
为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符,如下所示:
struct_pointer->title;
让我们使用结构指针来重写上面的实例,这将有助于您理解结构指针的概念:
实例
#include <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* 函数声明 */
void printBook( struct Books *book );
int main( )
{
struct Books Book1; /* 声明 Book1,类型为 Books */
struct Books Book2; /* 声明 Book2,类型为 Books */
/* Book1 详述 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Book2 详述 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 通过传 Book1 的地址来输出 Book1 信息 */
printBook( &Book1 );
/* 通过传 Book2 的地址来输出 Book2 信息 */
printBook( &Book2 );
return 0;
}
void printBook( struct Books *book )
{
printf( "Book title : %s\n", book->title);
printf( "Book author : %s\n", book->author);
printf( "Book subject : %s\n", book->subject);
printf( "Book book_id : %d\n", book->book_id);
}
当上面的代码被编译和执行时,它会产生下列结果:
Book title : C Programming Book author : Nuha Ali Book subject : C Programming Tutorial Book book_id : 6495407 Book title : Telecom Billing Book author : Zara Ali Book subject : Telecom Billing Tutorial Book book_id : 6495700
结构体大小的计算
C 语言中,我们可以使用 sizeof 运算符来计算结构体的大小,sizeof 返回的是给定类型或变量的字节大小。
对于结构体,sizeof 将返回结构体的总字节数,包括所有成员变量的大小以及可能的填充字节。
以下实例演示了如何计算结构体的大小:
实例
struct Person {
char name[20];
int age;
float height;
};
int main() {
struct Person person;
printf("结构体 Person 大小为: %zu 字节\n", sizeof(person));
return 0;
}
以上实例中,我们定义了一个名为 Person 的结构体,它包含了一个字符数组 name、一个整数 age 和一个浮点数 height。
在 main 函数中,我们声明了一个 Person 类型的变量 person,然后使用 sizeof 运算符来获取 person 结构体的大小。
最后,我们使用 printf 函数打印出结构体的大小,输出结果如下:
结构体 Person 大小为: 28 字节
注意,结构体的大小可能会受到编译器的优化和对齐规则的影响,编译器可能会在结构体中插入一些额外的填充字节以对齐结构体的成员变量,以提高内存访问效率。因此,结构体的实际大小可能会大于成员变量大小的总和,如果你需要确切地了解结构体的内存布局和对齐方式,可以使用 offsetof 宏和 __attribute__((packed)) 属性等进一步控制和查询结构体的大小和对齐方式。
tianqixin
429***967@qq.com
结构体中成员变量分配的空间是按照成员变量中占用空间最大的来作为分配单位,同样成员变量的存储空间也是不能跨分配单位的,如果当前的空间不足,则会存储到下一个分配单位中。
#include <stdio.h> typedef struct { unsigned char a; unsigned int b; unsigned char c; } debug_size1_t; typedef struct { unsigned char a; unsigned char b; unsigned int c; } debug_size2_t; int main(void) { printf("debug_size1_t size=%lu,debug_size2_t size=%lu\r\n", sizeof(debug_size1_t), sizeof(debug_size2_t)); return 0; }编译执行输出结果:
结构体占用存储空间,以32位机为例
tianqixin
429***967@qq.com
小羽
106***1689@qq.com
结构体数组:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXTITL 41 #define MAXAUTL 31 #define MAVXBKS 100 char * s_gets(char * st, int n); struct book { char title[MAXTITL]; char author[MAXAUTL]; float value; }; int main() { struct book library[MAVXBKS]; //book类型的结构体数组 int i; int index; printf("请问你要录入多少本书的信息\n"); do { scanf("%d", &index); } while (index > MAVXBKS); getchar(); for (i = 0; i < index; i++) { printf("请输入第%d本书的名称:\n",i+1); s_gets(library[i].title, MAXTITL); printf("输入其作者的名字:\n"); s_gets(library[i].author, MAXAUTL); printf("请输入书本的价格:\n"); scanf("%f", &library[i].value); getchar(); } for (i = 0; i < index; i++) { printf("%d\t%s 是 %s 写的 定价为%f元\n", i,library[i].title, library[i].author, library[i].value); } system("pause"); return 0; } char * s_gets(char * st, int n) { char * ret_val; char * find; ret_val = fgets(st, n, stdin); if (ret_val) { find = strchr(st, '\n'); //查找换行符 if (find) // 查找地址不为空 *find = '\0'; //在此处放入一个空字符 else while (getchar() != '\n') continue; //处理剩余字符 } return ret_val; }小羽
106***1689@qq.com
leesc
318***893@qq.com
可以在声明结构体时初始化结构体变量:
#include <stdio.h> int main(void) { struct Student { char name[50]; int gender; int age; } student2 = {"张三",0,30}; struct Student student1; printf("name:\n"); scanf("%s",student1.name); printf("gender:\n"); scanf("%d",&student1.gender); printf("age:\n"); scanf("%d",&student1.age); printf("student1 >>name = %s, gender = %d, age = %d\n", student1.name, student1.gender, student1.age); printf("student2 >>name = %s, gender = %d, age = %d\n", student2.name, student2.gender, student2.age); }leesc
318***893@qq.com
js
824***808@qq.com
参考地址
结构体数组
一个结构体变量中可以存放一组数据(如一个学生的学号,姓名,成绩等数据)。如果有10个学生的数据需要参加运算,显然应该用数组,这就是结构体数组。结构体数组与以前介绍过的数据值型数组不同之处在于每个数组元素都一个结构体类型的数据,它们分别包括各个成员(分量)项。
定义结构体数组
和定义结构体变量的方法相仿,只需说明其为数组即可。
struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }; struct student stu[3];以上定义了一个数组 stu,其元素为 struct student 类型数据,数组有 3 个元素。也可以直接定义一个结构体数组。如:
struct student { int num; .... }stu[3]; 或 struct { int num; ... }stu[3];结构体数组的初始化
与其它类型数组一样,对结构体数组可以初始化如:
struct student { int mum; char name[20]; char sex; int age; float score; char addr[30]; }stu[3] = {{10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"}, {10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"}, {10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"}};定义数组 stu 时,元素个数可以不指定,即写成以下形式:
stu[] = {{...},{...},{...}};编译时,系统会根据给出初值的结构体常量的个数来确定数组元素的个数。
当然,数组的初始化也可以用以下形式:
struct student { int num; ... }; struct student stu[] = {{...},{...},{...}};即先声明结构体类型,然后定义数组为该结构体类型,在定义数组时初始化。
从以上可以看到,结构体数组初始化的一般形式是在定义数组的后面加上:
结构体数组应用举例
下面例子说明结构体数组的定义和引用。
#include <stdio.h> #include <string.h> #include <stdlib.h> struct person { char name[20]; int count; }leader[3] = {{"Li", 0}, {"Zhang", 0}, {"Fun", 0}}; void main() { int i, j; char leader_name[20]; for(i = 1; i<= 10;i++) { scanf("%s", leader_name); for(j=0;j<3;j++) if(strcmp(leader_name, leader[j].name) == 0) leader[j].count ++; } printf("\n"); for(i=0;i<3;i++) printf("%5s: %d\n", leader[i].name, leader[i].count); system("pause"); }运行结果如下:
js
824***808@qq.com
参考地址
qq105677765
105***765@qq.com
使用结构数组存储书名/作者,结构体指针访问成员时,也可以对指针解引用再访问,如:*struct_pointer.title;(上面范例)。
#include<stdio.h> #include<string.h> char * s_gets(char*st, int n); #define MAXTITL 40 #define MAXAUTL 40 #define MAXBKS 100 // 书籍的最大数量 struct book { //简历 book 模板 char title[MAXTITL]; char author[MAXAUTL]; float value; }; int main(void) { struct book library[MAXBKS]; //book 结构类型数组 int count = 0; int index; printf("请输入书名:\n"); printf("按下 [enter] 键结束输入。\n"); while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL && library[count].title[0] != '\0') { printf("请输入作者:\n"); s_gets(library[count].author, MAXAUTL); printf("请输入价格:\n"); scanf("%f", &library[count++].value); while (getchar() != '\n') continue; //清理输入行 if (count < MAXBKS) printf("输入下一本书。\n"); } if (count > 0) // 如果数组内有存书籍 { printf("书的列表:\n"); for (index = 0; index < count; index++) // 遍历已存入的书籍, printf("%s - %s:$%.2f\n", library[index].title, library[index].author, library[index].value); // 将内容打印出来 } else printf("没有书。\n"); // 否则就打印没书 return 0; } char * s_gets(char * st, int n) //输入文本(作家)函数 { char * ret_val; char * find; ret_val = fgets(st, n, stdin); if (ret_val) { find = strchr(st, '\n'); //查找换行符 if (find) //如果地址不是NULL *find = '\0'; //在此处放置一个空字符 else while (getchar() != '\n') continue; } return ret_val; }qq105677765
105***765@qq.com
hooyubin
hoo***in@gmail.com
对一楼所讲内容的补充:结构体内存大小对齐原则
hooyubin
hoo***in@gmail.com
小小小韩
hhy***2877@163.com
对于案例代码的更改
在Vs 2022上运行访问结构成员-实例代码时候出现了报错
需要将 strcpy 改为 strcpy_s。
#include <stdio.h> #include <string.h> struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main() { struct Books Book1; /* 声明 Book1,类型为 Book */ struct Books Book2; /* 声明 Book2,类型为 Book */ /* Book1 详述 */ strcpy_s(Book1.title, "C Programming"); strcpy_s(Book1.author, "Nuha Ali"); strcpy_s(Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* Book2 详述 */ strcpy_s(Book2.title, "Telecom Billing"); strcpy_s(Book2.author, "Zara Ali"); strcpy_s(Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* 输出 Book1 信息 */ printf("Book 1 title : %s\n", Book1.title); printf("Book 1 author : %s\n", Book1.author); printf("Book 1 subject : %s\n", Book1.subject); printf("Book 1 book_id : %d\n", Book1.book_id); /* 输出 Book2 信息 */ printf("Book 2 title : %s\n", Book2.title); printf("Book 2 author : %s\n", Book2.author); printf("Book 2 subject : %s\n", Book2.subject); printf("Book 2 book_id : %d\n", Book2.book_id); return 0; }改正之后才能正常运行。
小小小韩
hhy***2877@163.com
初学者
245***4415@qq.com
参考地址
利用结构体的特性,实现柔性数组。
先看特性:
struct text1 { int num; char name[20]; int arr[]; }; struct text2 { int num; char name[20]; }; void main() { struct text1 t1; struct text2 t2; printf("结构体text1的大小为:%d \n", sizeof(t1)); printf("结构体text2的大小为:%d \n", sizeof(t2)); }此程序输出的结果为:
结构体text1的大小为:24 结构体text2的大小为:24
从结果可以看出,第一个结构体比第二个结构体多了一个参数 int arr[],但最后的结果确实两个结构体的大小相同。可以说明,在计算结构体时,如果结构体中存在未给定长度的数组,那么在计算时,将会忽略这个数组。
下面代码将演示如何实现柔性数组:
struct text1 { int num; char name[20]; int arr[]; }; void main() { struct text1 *t1; //期望arr是10个整形数组 int arrNum = 10; t1 = (struct text1*)malloc(sizeof(struct text1)+arrNum*sizeof(int));//给arr数组分配空间,申请(原数据结构的大小+arr数组的大小) t1->num = arrNum; //此时,就已经完成为数组arr分配空间,使用num来记录一下分配的个数 //如果在使用中arr数组个数不足,需要开辟更大的空间 int addNum = 10; struct text1 *pstruct=realloc(t1,sizeof(struct text1)+(t1->num+addNum)*sizeof(int)); if (pstruct!=NULL) {//为了防止开辟空间失败导致空间丢失 t1 = pstruct; t1->num += addNum; pstruct = NULL; } //给数组赋值 for (int i = 0; i <= t1->num - 1;i++) { t1->arr[i] = i; } //打印数组 for (int i = 0; i <= t1->num - 1;i++) { printf("%d ",t1->arr[i]); } //销毁数组 free(t1); t1 = NULL; }读者乍一看,可能感觉这样的作用不大,如果我们把数组换为其他数组类型呢?比如结构体
struct peoInfo { char name[20]; int age; char addr[50]; char tele[12]; }; struct ContractPeo { struct peoInfo* data; int sz;//联系人数量 int zone;//通讯录总空间大小 }con; void main() { //初始化通讯录 int initNum = 20; con.data = (struct data*)malloc(sizeof(struct peoInfo)+initNum*sizeof(int)); con.zone = initNum; //添加联系人,假如我们已经添加了20个联系人,达到了空间的上限,就需要开辟新的空间 con.sz = 20;//联系人达到空间上限 int addNum = 10;//依次增加十个人的空间上限 struct people *p=(struct peoInfo*)realloc(con.data,(addNum+initNum)*sizeof(struct peoInfo)); if (p!=NULL) { con.data=p; p = NULL; } con.zone += addNum;//这个时候,空间的上限变成了30 // TO DO....... //我们将联系人设置为0进行测试 con.sz = 0; for (int i = 0; i <= con.zone-1;i++) { con.data->name[i] = i; con.data->tele[i] = i; con.sz++;//增加完一个联系人 } printf("姓名 电话\n"); for (int i = 0; i <= con.zone - 1; i++) { printf("%d ", con.data->name[i]); printf("%d ", con.data->tele[i]); printf("\n"); } free(con.data); con.data=NULL; }初学者
245***4415@qq.com
参考地址
平平
125***7528@qq.com
双向循环链表
双向循环链表(Doubly Circular Linked List)是一种数据结构,它由多个节点(Node)组成,每个节点包含两个指针(Pointer),分别指向它的前一个节点和后一个节点,最后一个节点的后继指向头结点,头结点的前驱指向最后一个节点,形成一个环状结构。
下面是一个简单的双向循环链表的实现,包含节点的结构体和常见操作函数的实现:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #define SHOW_MODE 0 #define FIND_MODE 1 #define DELL_MODE 2 typedef struct list_link_node { int data; struct list_link_node * pre; struct list_link_node * next; }listnode,*listlink; listlink Creat_list_node();//创建节点 int Mode_Select(listlink head );//模式选择 int Tail_Add_Node(listlink head);//尾部插入 listlink Display(listlink head,int mode);//遍历节点 int Head_Add_Node(listlink head);//头部插入 int ADD_Anywhere(listlink head);//任意节点插入(调用了Display遍历至输入数据相等处) int Dele_Anywhere(listlink head);//删除任意节点 int ADD_Anywhere(listlink head) { if(head==NULL) { printf("failed!\n"); return 0; } if(head->next==head) { printf("empty!\n"); return 0; } listlink add_node = Display(head,FIND_MODE);//遍历 if(add_node ==(listlink) 0) { printf("add falied!\n"); return -1; } listlink new_node=Creat_list_node();//新建节点 if(new_node==(listlink) -1) { printf("new falied!\n"); return -1; } printf("请输入要添加的数据:\n"); scanf("%d",&new_node->data); new_node->next=add_node->next; new_node->next->pre=new_node; new_node->pre=add_node; add_node->next=new_node; return 0; } int Dele_Anywhere(listlink head) { if(head==NULL) { printf("failed!\n"); return 0; } if(head->next==NULL) { printf("empty!\n"); return 0; } listlink del_node = Display(head,DELL_MODE);//删除模式(遍历) if(del_node ==(listlink) 0) { printf("del falied!\n"); return -1; } del_node->pre->next=del_node->next; del_node->next->pre=del_node->pre; del_node->next=NULL; del_node->pre=NULL; free(del_node); return 0; } int Head_Add_Node(listlink head) { if(head==NULL) { printf("failed!\n"); return -1; } listlink new_node=Creat_list_node();//初始化新节点 if(new_node==(listlink)-1) { printf("tail node failed!\n"); return -1; } printf("请输入新数据:\n"); scanf("%d",&new_node->data); new_node->next=head->next; //新节点next 赋值为 传入节点next new_node->next->pre=new_node; //此时新节点next同等 传入节点,该节点pre 赋值为 新节点 new_node->pre=head; //新节点pre 赋值为 传入节点 head->next=new_node; //传入节点next 赋值为 新节点 return 0; } listlink Creat_list_node() { listlink node=(listlink)malloc(sizeof(listnode)); //指向堆,用完不会自动释放 if(node==(listlink)NULL) { printf("listlink malloc failed!\n"); return (listlink)-1; } memset(node,0,sizeof(listnode)); node->pre=node; node->next=node; return node; } int Tail_Add_Node(listlink head) { if(head==NULL) { printf("failed!\n"); return -1; } listlink new_node=Creat_list_node();//创建新节点 if(new_node==(listlink)-1) { printf("tail node failed!\n"); return -1; } printf("请输入新数据:\n"); scanf("%d",&new_node->data);//数据域 new_node->pre=head->pre; //新节点pre 赋值为 传入节点pre new_node->pre->next=new_node; //此时用 新节点pre 等于传入节点,成员next赋值为新节点 new_node->next=head; //传入节点next 赋值为 新节点 head->pre=new_node; //传入节点pre 赋值为 新节点 //"蛇头咬蛇尾" return 0; } listlink Display(listlink head,int mode) { if(head==NULL) { printf("adnormal!\n"); return (listlink)0; } if(head->next==head) { printf("empty!\n"); return (listlink)0; } int data=0; if(mode==FIND_MODE||mode==DELL_MODE) { printf("请输入要检索的数据!\n"); scanf("%d",&data);//要检索的值 } //初始化节点 赋值为 传入节点next;当前节点 不等于 传入节点;当前节点 赋值为 当前节点next for(listlink temp_node=head->next;temp_node!=head;temp_node=temp_node->next) { if(mode==SHOW_MODE) { printf("%d\n",temp_node->data); } if((mode==FIND_MODE||mode==DELL_MODE)&&temp_node->data==data)//判断当前节点成员数据值与输入的数据值 { printf("hit the number!\n"); return temp_node;//返回当前节点地址 } } if(mode==FIND_MODE||mode==DELL_MODE) { printf("找不到数据!\n"); return 0; } return (listlink)0; } int Mode_Select(listlink head) { if(head==NULL) { printf("failed!\n"); return 0; } int select_num=0; while (1) { system("clear"); printf("-------1.尾插链表-----------\n"); printf("-------2.头插链表-----------\n"); printf("-------3.指定位置添加数据----\n"); //bian printf("-------4.指定位置删除数据----\n"); //bian printf("-------5.检索数据-----------\n"); //bian printf("-------6.移动数据-----------\n"); //bian printf("-------7.显示链表------------\n"); printf("-------8.退出链表!-----\n"); scanf("%d",&select_num); switch (select_num) { case 1:Tail_Add_Node(head); break; case 2:Head_Add_Node(head); break; case 3:ADD_Anywhere(head); break; case 4:Dele_Anywhere(head); break; case 5:Display(head,FIND_MODE); break; case 6:printf("-------1.尾插链表------\n"); break; case 7:Display(head,SHOW_MODE); break; case 8:printf("-------8.退出链表!------\n"); return 0; default:printf("错误的命令!请重新输入:\n"); break; } sleep(2); } return 0; } int main(int argc, char const *argv[]) { listlink head=Creat_list_node(); if(head==(listlink)-1) { printf("creat head failed!\n"); return -1; } Mode_Select(head); return 0; }平平
125***7528@qq.com
Hulk
150***2122@qq.com
结构体内存对齐的规则很简单:
一、成员变量内存相对起始位置为数据类型所占内存的整数倍(例如:int 类型数据相对起始位置必须是结构体中4字节的整数倍),若不足则需要对齐不足部分的内存(内存补充给前一个变量)。
二、结构体所占总内存为其成员变量中所占空间最大数据类型的整数倍。
三、结构体中每个成员相对于结构体起始地址的偏移量必须是该成员大小的倍数。
其中,最宽基本类型指的是 long double、double 和 long long 中占用空间最大的类型。如果结构体中没有这些类型的成员,则以 int 或者 char 作为最宽基本类型。
以下是一个示例,展示了一个结构体的内存对齐过程:
struct example { char a; // 1 byte int b; // 4 bytes double c; // 8 bytes short d; // 2 bytes };根据内存对齐规则,该结构体中的成员变量将按照以下方式进行排列:
由于 int 和 double 的大小都是 4 的倍数和 8 的倍数,因此它们的偏移量和结构体总大小都可以被 4 和 8 整除,而 short 的大小为 2,因此需要填充 6 个字节以满足偏移量为 8 的要求。
Hulk
150***2122@qq.com