结构体可以理解为自定义的数据类型,它是由一批数据组合而成的结构型数据
struct 结构体名字 {
成员1;
成员2;
...
成员n;
};
案例:
#include
#include
struct student {
char name[100];
int age;
char gender;
};
int main() {
struct student s1;
strcpy(s1.name, "zhangsan");
s1.age = 18;
s1.gender = 'M';
printf("name:%s,age:%d,gender:%c", s1.name, s1.age, s1.gender);
}
如果是写在了函数的里面表示我们把它定义在了局部位置,只能在本函数中使用
写在了函数的外面则表示我们把它定义在了全局位置,在整个程序中都可以使用
定义三个学生对象,并且将他们放置于数组中,最后遍历输出
#include
#include
struct student {
char name[100];
int age;
char gender;
};
int main() {
struct student s1 = {
"zhangsan",
18,
'M'
};
struct student s2 = {
"lisi",
18,
'M'
};
struct student s3 = {
"wangwu",
18,
'M'
};
struct student ans[3] = {s1, s2, s3};
for (int i = 0; i < 3; i++) {
printf("name:%s,age:%d,gender:%c\n",ans[i].name, ans[i].age, ans[i].gender);
}
}
在我们使用结构体时是否会觉得在定义时太过麻烦,这可以用起别名的方式进行简化
举例:
#include
#include
typedef struct student {
char name[100];
int age;
char gender;
} stu;
int main() {
stu s = {"zhangsan", 18, 'M'};
printf("name:%s, age:%d, gender:%c", s.name, s.age, s.gender);
}
注意如果要定义别名的话,在定义结构体时需要在之前加上typedef
在函数中可以传递结构体
其中有两种情况:
#include
#include
typedef struct student {
char name[100];
int age;
char gender;
} stu;
// 因为这个函数用到了结构体,所以这个函数的声明必须写在函数的下面,否则程序会报错
void change_age(stu s) {
printf("修改前的数据为:name:%s, age:%d, gender:%c\n", s.name, s.age, s.gender);
printf("请输入修改后的年龄为:");
scanf("%d", &s.age);
printf("修改后的数据为:name:%s, age:%d, gender:%c\n", s.name, s.age, s.gender);
}
int main() {
stu s = {"zhangsan", 18, 'M'};
change_age(s);
}
像这一段代码所改变的仅仅只是在函数中的数据,并不会对主函数中的数据产生影响,真正想要对主函数的数据产生影响的话还是得要用到第二种传递方式
#include
#include
typedef struct student {
char name[100];
int age;
char gender;
} stu;
// 因为这个函数用到了结构体,所以这个函数的声明必须写在函数的下面,否则程序会报错
void change_age(stu* p) {
printf("修改前的数据为:name:%s, age:%d, gender:%c\n", (*p).name, (*p).age, (*p).gender);
printf("请输入修改后的年龄为:");
scanf("%d", &((*p).age));
}
int main() {
stu s = {"zhangsan", 18, 'M'};
stu* p = &s;
change_age(p);
printf("修改后的数据为:name:%s, age:%d, gender:%c\n", s.name, s.age, s.gender);
}
如果结构体中的成员的类型是其它的结构体,那么就用到了结构体的嵌套
#include
#include
// 定义一个结构体表示学生,其中的成员有姓名,年龄,性别,联系方式,联系方式又是一个结构体,其中包含手机号和电子邮箱
typedef struct connection {
char phone_number[20];
char email[30];
} con;
// 因为student中用到了connection,所以student必须定义在connection之后,否则会报错
typedef struct student {
char name[100];
int age;
char gender;
con c;
} stu;
int main() {
stu s = {"zhangsan", 18, 'M', "12345678912", "[email protected]"};
printf("name:%s, age:%d, gender:%c, phone_number:%s, email:%s\n", s.name, s.age, s.gender, s.c.phone_number, s.c.email);
}
答案是:只能放在自己类型所占的字节数(char为1,int为4等等)整数倍的内存地址上
答案是:结构体的总长度是最长数据类型的整数倍
如下方的结构体:
struct nums {
//double长为8
double a;
//char长为1
char b;
//int长为4
int c;
//char长为1
char d;
};
//那么你会不会以为这么一个结构体的长度为14?这样想你就掉入陷阱了
我们最先放下的数据是a,因为内存地址是从0开始的,0是double数据类型的长度——8的倍数,所以前8个字节(0-7)用于放a
其次放下的数据是b,因为char类型的长度仅仅只有1,所以第9个字节(8)就用来放b
再之后是c,轮到它时,我们已经走到了9(第十个字节),但是下一个4的倍数为12,所以我们要一直走到12(第十三个字节)才能放下c
最后是d,它最后放在16(第十七个字节)上
那么这个结构体的长度为17?
又错了
还记得上方的第二点吗?
17之后下一个能被8整除的数为24,这才是这个结构体真正的长度
看了上方的解析,其实我们能得出一个结论,在定义结构体时我们应该从小到大依次定义结构体中的数据,这就是最节省结构体空间的定义方式