一、结构体的的概念及定义
1、概念:之前学过数组内部是相同类型的元素,而结构体就是内部不同数据类型的一个整体
2、结构体的定义
struct student
{
变量; // 称为结构体变量或属性
}
//根据结构体类型student,定义结构体变量,变量名为s(此阶段分配存储空间)
struct student s={ }; // 赋值的时候只能在定义结构体的时候同时赋值
二、内存分析
1、对齐算法:结构体所占用内存空间的大小,一定是结构体中最大成员所占用存储空间的倍数。
struct Student
{
int age; // 4个字节
char *name; // 8个字节
}stu;
结构体所占用的字节:16个字节(8的倍数);
2、内存分配:定义结构体类型时不会分配内存空间,只有当赋值的时候才能分配存储空间。
三、注意点
1、定义结构体变量的三种方式:
1>从类型和变量进行考虑先定义类型(相当于int、double等),再定义变量
struct student
{
int age;
};
struct student stu;
2>定义类型的同时定义变量
struct student
{
int age;
} stu;
3>定义类型的同时定义变量,但是省略类型名称
struct
{
int age;
} stu;
2、结构体类型的作用域
定义在函数内部:从定义那一行开始,到函数或代码块结束。(跟局部变量一样)
定义在函数外部:从定义那一行开始,到程序结尾。(跟全局变量一样)
四、复杂类型的结构体
1、结构体数组(结构体中定义结构体):
struct student stu[3] = { { },{ },{ } } // 结构体数组中含有三个结构体
数组修改方式:
错误修改:stu[0]={ };
正确修改:stu[0].age=10;
2、指向结构体的指针
struct student *p;
p=&stu;
★有三种方法访问结构体属性:
方法1:stu.age;
方法2:(*p).age;//代表指针访问结构体中的age属性
方法3: p->age;//代表指针访问结构体中的age属性 (最常用)
3、结构体嵌套
概念:在结构体中调用结构体。
struct names
{
int ages;
int years;
}name;
struct Student
{
name *stuname; // 嵌套结构体name
int banji;
}stu;
五、结构体的sizeof问题详解
如题
#include <stdio.h>
struct stu
{
char names[10];
long num;
char sex;
int age;
float score;
char address[10];
};
void main()
{
stu stu2;
printf("%d %d %d %d\n",sizeof(long),sizeof(char),sizeof(int),sizeof(float));
printf("%d\n",sizeof(stu2));
}
运行结果:
4 1 4 4
40
过程详解:
结构体每个保存都是按照最长的定义类型来的。
字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是最宽基本类型成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
比如上面最长的是int和long 都是4个字节
见下示例图。
口口口口
口口口口
口口 char names[10]
口口口口 long num
口 char sex
口口口口 int age
口口口口 float score
口口口口
口口口口
口口 char address[10]