C语言结构体学习笔记

cnbigmx 萌新

C语言结构体

1、结构体的定义

结构体多用于将不同类型的数据组合为一个整体,以便于使用。比如统计学生的信息时,包含姓名、学号、年龄、性别等属性,如果每一个属性都定义对应的变量,不方便管理而且当有多名学生时,变量名就难以定义和区分,此时就可以使用结构体进行管理不同类型的数据组合。

声明结构体的一般形式:

1
2
3
struct 结构体名称 {
成员表列
};
1
2
3
4
5
6
7
8
9
10
11
12
struct Student {
int age;
int Id;
char name[20];
char gender;
};
int main()
{
struct Student s = {18,202158501200,"zhangsan",'n'};
scanf("%d %d %s %c",&s.age,&s.id,s,name,&s.gender);
return 0;
}

声明结构体的一次性形式:

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

只能使用一次,不推荐这种方式

1
2
3
4
5
6
7
8
9
10
11
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);
}

typedef 声明结构体

typedef的作用就是起别名。例如,typedef int INGETER;即INGETER可以替换int,此时结构体名称可以省略

1
2
3
typedef struct 结构体名称 {
成员表列
}别名;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
typedef struct Student {
int age;
int Id;
char name[20];
char gender;
}stu,*pstu;
// stu 等价于 struct Student, *pstu 等价于 struct Student*
int main()
{
stu s = {18,202158501200,"zhangsan",'n'};
stu *p=&s;
pstu p1=&s;
return 0;
}

2、结构体的使用

结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<stdio.h>
struct Student {
int age;
int Id;
char name[20];
char gender;
};
int main()
{
struct Student s = {18,202158501200,"zhangsan",'n'};
printf("%d %d %s %c",s.age,s.id,s.name,s.gender);
scanf("%d %d %s %c",&s.age,&s.id,s,name,&s.gender);
return 0;
}

结构体数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
struct Student {
int age;
int Id;
char name[20];
char gender;
};
int main()
{
struct Student s[3];
for(int i=0;i<3;i++){
scanf("%d %d %s %c",&s[i].age,&s[i].id,s[i].name,&s[i].gender);
}
return 0;
}

其中(s.age,s.id,s.name,s.gender).是成员选择运算符(对象)。

3、结构体对齐

一般来说结构体的大小必须是其最大成员的整数倍。目的是为了让cpu高效的去取内存上的数据。

暂时不用仔细研究

示例一:

1
2
3
4
5
6
struct Student {
int age;
int Id;
char name[20];
char gender;
} s;

s 应该是4+4+20+4=32个字节,而不是4+4+20+1=29个字节。

1
2
3
4
struct Stuendt2 {
double score;
short age;
} s1;

s1 应该是8+8=16个字节,而不是 8+2=10个字节。

示例二:

1
2
3
4
5
struct Stuendt2 {
double score;
int num;
short age;
} s2;

s2 则是16个字节。因为最大字节为8,且int 与 short 相邻且总大小小于8,所以共用一个8字节。

所以可以将小字节类型相邻,节省内存。

4、结构体指针

一个结构体变量的指针就是改变量所占据的内存段的起始地址。可以设置一个指针变量,用它指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体(数组)中的元素,以便于通过结构体指针快速访问结构体内的每个成员。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Student {
int age;
int Id;
char name[20];
char gender;
};
int main()
{
struct Student s[3];
struct Student s1 = {18,202158501200,"zhangsan",'n'};
struct Student *p;
p=&s1;
printf("%d %d %s %c",p->age,p->id,p->name,p->gender);
for(int i=0;i<3;i++){
scanf("%d %d %s %c",&s[i].age,&s[i].id,s[i].name,&s[i].gender);
}
p=s; // p=&s[0];
p=p+1; // p=&s[1];

p=(struct Student*)malloc(szieof(struct Student));
p->age=10;
p->id=20215;
p->gender='m';
strcpy(p->name,"cnbigmx");// 字符串不能直接赋值
return 0;
}

其中*p->age,*p->id,*p->name,*p->gender)->是成员选择运算符(指针),p->age等价于(*p).age