结构体其实就是用来自己定义新的数据类型;
一、相关介绍
格式:
struct 名字{
成员 1;
成员 2;
。 。 。
成员 n;
};//定义新的数据类型为:struct 名字
二、定义方式
第1种:先定义数据类型,再用数据类型定义变量;
第一步: 定义数据类型
struct Stu
{
char name[32];
int ID;
float score;
};//已经定义好一种新的数据类型,叫struct Stu
已经定义好新的数据类型,叫struct Stu,类似于int a中的int。
仅仅有数据类型,不定义变量,计算机不开辟空间
第二步: 用自己定义的数据类型, 定义变量
struct Stu per1;
struct Stu per1;//类比int a,其中struct Stu类似于int属于数据类型,而per1类似a属于变量名;
定义一个变量,变量名叫per1, per1的数据类型 struct Stu 类型;此时计算机给 per1 开辟sizeof(struct Stu)大小空间
第2种:定义数据类型, 同时用数据类型定义变量;
struct Stu
{
char name[32];
int ID;
float score;
}per1;
定义一个变量,变量名叫per1,per1的数据类型 struct Stu 类型;
计算机给 per1 开辟sizeof(struct Stu)大小空间
第3种:无名结构体 只能在定义数据类型的同时定义变量;
struct
{
char name[32];
int ID;
float score;
}per1;
没有数据类型名字,括号后面直接加变量名,使用。
三、结构体取成员:
普通的变量:格式:变量名.成员
例:
struct Stu
{
char name[32];
int ID;
float score;
};
struct Stu per1;
取成员:
per1.name 对应的数据类型为 char[32]=>%s
per1.ID 对应的数据类型为 int=>%d
per1.score 对应的数据类型为 float=>%f
#include <stdio.h>
struct Stu
{
char name[32];
int id;
float score;
};
int main()
{
struct Stu per[3]={0};
for(int i=0;i<3;i++)
{
scanf("%s",per[i].name);
getchar();
scanf("%d",&per[i].id);
getchar();
scanf("%f",&per[i].score);
getchar();
}
for(int i=0;i<3;i++)
{
printf("%s %d %f\n",per[i].name,per[i].id,per[i].score);
}
return 0;
}
指针变量取成员:
格式:指针变量名->成员;
例:
struct Stu
{
char name[32];
int ID;
float score;
};
struct Stu per1; //结构体变量名不是地址
struct Stu *p = &per1;
在上述代码中取成员:
p->name 对应的数据类型为 char[32]=>%s
p->ID 对应数据类型为 int=>%d
p->score 对应数据类型为 float=>%f
#include <stdio.h>
struct Stu
{
char name[32];
int id;
float score;
};//注意分号不能少
int main()
{
struct Stu per = {0};
struct Stu *p = NULL;
p = &per;
printf("输入name:\n");
scanf("%s",p->name);
getchar();//吸收输入结束按下后的回车键
printf("输入id:\n");
scanf("%d",&p->id);
getchar();
printf("输入score:\n");
scanf("%f",&p->score);
getchar();
printf("name=%s id=%d score=%.1f\n",per.name,per.id,per.score);
return 0;
}
运行结果:
输入name:
小明
输入id:
1001
输入score:
99
name=小明 id=1001 score=99.0
四、结构体的初始化:
1.完全初始化 -- 依次赋值
struct Stu per={"小名",1001,95.5};//完全初始化
2.部分初始化 -- 依次赋值,未赋值的系统给 0
struct Stu per={"小名",1001};//部分初始化,依次赋值,未赋值补0
3.只定义变量,不赋值,遵循全局变量和局部变量自身的原则
struct Stu per;//没有初始化,局部变量产生随机数
4.取成员初始化
struct Stu per={.name="小名",.score=95.5};
5.从键盘输入
struct Stu per={0};
scanf("%s%d%f",per.name,&per.id,&per.score);
五、结构体的大小:
- 利用sizeof();//括号内写变量名或结构体数据类型
- 自行计算
计算结构体空间大小
第一步:确定对齐方式-以下三个中的较小者
-
- 先看系统,64位系统为8字节,32位系统为4字节。
- 看结构体中最大成员的大小(数组看数组的元素类型)
- #pragma pack(2/4/8)括号中写几就是几
第二步: 结构体中除第一个成员外, 其他成员距离首地址的偏移量, 必须是对齐方式或者自身大小中较小者的整数倍!
第三步:结构体的整体大小,必须是对齐方式的整数倍!
#include <stdio.h>
/*
结构体大小
1.对齐方式 int或float 4
2.结构体中除第一个成员外,其他成员距离首地址的偏移量,必须是对齐方式或者自身大小中较小者的整数倍;
3.结构体的整体大小,满足对齐方式的整数倍
*/
struct Stu
{
char name[28];
int id;
float score;
};
int main()
{
struct Stu per={0};
long num=sizeof(per);
printf("sizeof=%ld\n",num);
return 0;
}
输出的结果为:sizeof=36;
分析一下:
第一步.确定对齐方式:
使用的计算机为64位系统,8字节,结构体中有char->1字节、int->4字节、float->4字节,结构体中的最大字节为4字节,与系统相比,取较小的,也就是4字节。即对齐方式为4字节。
第二步.
结构体中除第一个成员外,也就是除去 char name[26];代码为char name[28],我用26讲,更具代表性。
分析第二个成员int id;char name[26]占据26字节,对齐方式为8字节,而int自身4字节;关键的一点:int id前如果为26字节,不是4字节的倍数,不符合条件,系统默认有再前面补2字节,此时int前有28字节,是4字节的倍数;(如果是char name[28],int id前就有28字节,不用补,如果是25,就还需要补3字节……)
分析第三个成员float score;float score前面系统已分配了28+4字节的空间,对齐方式为8字节,而float自身4字节,32字节刚好是4字节的整数倍,id空间和score空间之间系统不再额外分配空间;算上float自身4字节,此时已经分配空间为36字节。以此类推……
第三步、结构体的整体大小,必须是对齐方式的整数倍!
此时结构体的空间为36,刚好是对齐方式4字节的整数倍,系统也不再分配空间了(若所有成员算完,空间为34字节,不是4的倍数,系统会补2字节到最后一个成员后面,此时空间就为36字节了。如果算完空间为37,系统会再向结构体中的最后一个成员:本例是float后面补3字节,此时空间就为40字节,只多不少)