C语言中的结构体

结构体其实就是用来自己定义新的数据类型;

一、相关介绍

       格式:

         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);

五、结构体的大小:

  1. 利用sizeof();//括号内写变量名或结构体数据类型
  2. 自行计算

计算结构体空间大小

第一步:确定对齐方式-以下三个中的较小者

    • 先看系统,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字节,只多不少)

  • 47
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值