为什么要有结构
char -128+127
short -32768+32767
int
long
学生:
int num1;
char name1[20];
int score1;
int num2;
char name2[20];
int score2;
int num3;
char name3[20];
int score3;
结构体定义
一般声明
struct 结构体名
{
成员列表------《可以为任意数据类型》
int a;
int *p ;
void(*p)(void);
char b[200];
struct ---等
};
嵌套结构体声明
一般嵌套
1.
struct A{
int a;
int b;
};
struct B{
int b;
struct A a;
};
2.
/*
struct A{
int a;
struct A b;
};*/ 错误定义
struct A{
int a;
struct A *p;
}; //声明是对的;
互相嵌套
/*
struct A{
int a;
struct B b;
};
struct B{
int b;
struct A a;
};*/错误的声明方式
struct A{
int a;
struct B *b;
};
struct B{
int b;
struct A *a;
};
定义
1.
struct stu{
int num;
char name[20];
int score;
};//频率非常高
struct stu a;
2.
struct stu{
int num;
char name[20];
int score;
}a; //会见到
struct stu b;
3.
struct {
int num;
char name[20];
int score;
int age;
}a; //不常用
4.
typedef struct stu{
int num;
char name[20];
int score;
}STU,*PSTU; //会见到
STU a; //定义了一个srtuct stu结构体变量 与 struct stu a等价
PSTU P; //定义了一个指向struct stu 结构变量的指针 与struct stu *p等价
5.结构体数组
struct stu{
int num;
char name[20];
int score;
}a; //会见到
struct stu b[10];//int a[10];
使用
定义 及 初始化://int a=3;
//指定初始化:往往应用在结构体成员非常多的情况
struct stu a={ //int a=3;
.num =1,
.name ="xiaohe",
.score = 100,
};
struct stu a={ //int a=3;
num:1,
name:"xiaohe",
score:100,
};
//顺序初始化:一般成员非常少的情况下
struct stu a={ //int a=3;
1,
"xiaohe",
100,
};
//**数组初始化
int a[]={1,2,3,4,5};
int a[5]={1,2,3,4};//未初始化的空间会被编译器初始化成零
int a[5]={[0]=1,[2]=3};
如果未初始化:
全局变量:会被编译器初始化成0
局部变量:里面将就内存的值,随机值
//****
struct stu{
int num;
char name[20];
int score;
}a; //会见到
struct stu b[2]={
{1,"xiaohe",100},
{2, "xiaohehe",101},
};
struct stu b[2]={
[0]={1,"xiaohe",100},
[1]={
.num = 2,
.name = "xiaohehe",
.score =101
},
};
b[0].num
b[1].num
赋值
//int a ;a =3
struct stu{
int num;
char name[20];
int score;
};
/*
struct stu b;
b={ //error,只能在初始化使用
.num = 2,
.name = "xiaohehe",
.score =101
}*/
1.单个赋值
struct stu b;
b.num = 1;
//b.name = "xiaohe" //error //char s[10];s="niahoa" ---error
strcpy(b.name,"xiaohe")
b.score = 100;
2.整体赋值
1.结构体变量b = 结构体变量a
struct stu a={ //int a=3;
.num =1,
.name ="xiaohe",
.score = 100,
};
struct stu b = a;
2.内存搬移函数
memcpy(void *dest, const void *src, size_t n);
memcpy(&b,&a,sizeof(struct stu));
操作
1.单个操作(直接操作)
变量名.成员名----------得到的是成员名的本身属性
a.num
a.name
1.结构体指针
(内存:线性唯一,没有数据类型:程序猿按照数据类型的方式去操作内存)
指针:1.地址,2操作方式
定义:
struct stu{
int num;
char name[20];
int score;
};
struct stu *p; ----一个指针,指向了一个内存地址,按照结构体的方式操作内存
struct stu a={ //int a=3;
.num =1,
.name ="xiaohe",
.score = 100,
}
p=&a;
通过指针间接操作结构体空间:
指针名->成员名 :得到的是成员的本身属性
(*指针名).成员名 :同上,等价
2.结构体指针作函数参数:程序猿的必杀技
同其他指针作参数一样,哦也
结构体之嵌套define
struct A{
int a;
#define M 3
#define M1 4
};
结论:无任何意义, 可能:a的取值选项
结构体之字节对齐(结构体之五星重点)
1.结构体之内对齐
(作用:决定了每个成员的存放地址)
每个成员对齐值 与 系统对齐值比较: 取最小的那个
成员对齐值: 系统的对齐值:默认是4 ,可以修改 #pragma pack(4) ----数字就是对齐值,以2的次方改
char 1 -------1 ,4 -----1 addr%1 ==0
short 2 -------2 , 4 -----2 addr%2 ==0
int 4 -------4 , 4 -----4 addr%4 ==0
2.结构体之外对齐
每个成员比较后的对齐值中:取最大的
1
4 4
1
3.结构体之地址对齐
结构体外对齐值 与系统地址对齐值相比(默认为4 ,可修改 __attribute((aligned(4))) 同上):取最大的
注意: ARM 的 cpu 每次取值是从地址 addr 取值,其中 addr 满足 addr%4 == 0;
1结构体之内对齐 ----针对结构体内的对齐
2结构体之外对齐 ----
3结构体之地址对齐---- 2、3是针对万一有结构数组的情况,所以也得满足
注意:
情况一:
结构体没有使用 attrribute时,对齐方式由1和2来确定;
1来确定每个成员存放的位置;
2来确定下一个结构体存放的位置;
情况二:
结构体使用了attribute时,对齐方式由1,2,3,共同确定;
1来确定每个成员存放的位置;
2和3来确定下一个结构体存放的位置;
修改结构体内成员对齐的默认:#program park(4)
修改结构体外对齐2的n次方的默认:__attribuate((aligned (4)))