一丶结构体
定义:
用户自定义的数据类型,在结构体中可以包含若干个不同类型数据的成员变量(也可以相同),使这些数据项组合起来反映某一个信息
格式:
struct 结构体名
{数据类型 成员变量1;
数据类型 成员变量2;
数据类型 成员变量3;};
二丶结构体变量
定义:
通过结构体类型定义的变量
格式:
1. 先定义结构体,在定义结构体变量
#include <stdio.h>
struct student
{
int id;
int age;
float score;
};
int main(int argc, char const *argv[])
{
struct student stu;
return 0;
}
2. 定义结构体的同时,定义结构体变量
#include <stdio.h>
struct student
{
int id;
int age;
float score;
} stu;
int main(int argc, char const *argv[])
{
return 0;
}
3.缺省结构体名定义结构体变量
#include <stdio.h>
struct
{
int id;
int age;
float score;
} stu;
int main(int argc, char const *argv[])
{
return 0;
}
赋值:
1. 定义变量时直接用大括号赋值
#include <stdio.h>
struct student
{
int id;
int age;
float score;
};
int main(int argc, char const *argv[])
{
struct student stu = {1, 20, 88};
return 0;
}
2.定义变量时未初始化,然后对变量单独赋值
#include <stdio.h>
struct student
{
int id;
int age;
float score;
};
int main(int argc, char const *argv[])
{
struct student stu;
stu.id = 1;
stu.age = 20;
stu.score = 88;
return 0;
}
3.点等法赋值
#include <stdio.h>
struct student
{
int id;
char name[32];
int age;
float score;
};
int main(int argc, char const *argv[])
{
struct student stu = {
.id = 1,
.age = 20,
.score = 88
};
return 0;
}
访问:
通过.访问
:结构体变量名.成员变量名
scanf("%d %d %f %s", &stu.id, &stu.age, &stu.score, stu.name);
// stu.name就不用加&,因为这个数组名本身就是地址
printf("%d %d %f\n", stu.id, stu.age, stu.score);
三丶结构体数组
概念
结构体类型相同的变量组成的数组
格式:
1. 定义结构体同时定义结构体数组
struct student
{
int id;
int age;
float score;
} stu[3];
2.先定义结构体,然后定义结构体数组
#include <stdio.h>
struct student
{
int id;
int age;
float score;
};
int main(int argc, char const *argv[])
{
struct student stu[3];
return 0;
}
初始化
1.定义结构体数组同时赋值
#include <stdio.h>
struct student
{
int id;
int age;
float score;
};
int main(int argc, char const *argv[])
{
struct student stu[3] = {
{1, 20, 88},
{2, 21, 89},
{3, 19, 90}
};
return 0;
}
2. 先定义结构体数组,在对数组的每一个元素分别赋值
#include <stdio.h>
struct student
{
int id;
int age;
float score;
} stu[3];
int main(int argc, char const *argv[])
{
stu[0].id = 1;
stu[0].age = 20;
stu[0]. score = 88;
return 0;
}
结构体数组大小
结构体类型大小*元素个数
sizeof(结构体数组名);
结构体输入输出(for循环)
#include <stdio.h>
struct student
{
int id;
int age;
float score;
} stu[3];
int main(int argc, char const *argv[])
{
for (int i = 0; i < 3; i++)
{
scanf("%d %d %f", &stu[i].id, &stu[i].age, &stu[i].score);
}
return 0;
}
四丶结构体指针
概念:
指向结构体变量的指针
定义格式:
struct 结构体名 *结构体指针名;
#include <stdio.h>
struct student
{
int id;
int age;
float score;
} stu1, stu2;
struct work
{
int id;
int age;
float score;
} w1, w2;
int main(int argc, char const *argv[])
{
struct student *p = &stu1;
struct student *p1 = &w1; // 错误,结构体类型不匹配
return 0;
}
赋值:
// ->:指向的
格式:指针变量名 -> 成员变量名
p -> id = 1;
p -> age = 20;
p -> score = 88;((*p).score)
格式:指针变量名 -> 成员变量名
p -> id = 1;
p -> age = 20;
p -> score = 88;((*p).score)
#include <stdio.h>
struct student
{
int id;
int age;
float score;
} stu1;
int main(int argc, char const *argv[])
{
struct student *p = &stu1;
scanf("%d %d %f", &p->id, &p->age, &p->score);
printf("%d %d %f\n", p->id, p->age, (*p).score);
return 0;
}
大小:
本质是指针,与操作系统有关,64位为8,32位为4
五丶结构体大小
结构体大小并不是简单的将每个结构体成员的大小相加就能得到的,可以用
sizeof(struct 结构体名); // 结构体类型大小
结构体内存对齐规则
将结构体成员变量所占字节大小与编译器默认对齐数(64位:8,32位:4)相比较,取较大值从0地址处开始开辟,如果第一个成员变量存放后剩余内存可以存放下一个变量,则不需要开辟,否则就继续按结构体内存对齐原则向下开辟,结构体大小等于所有变量开辟内存大小。
//64位操作系统,默认对齐数为8
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct demo
{
short a; // 2 开辟8字节,short存储结束后还剩6字节
int b; // 4 int 4字节继续存储于剩余的6字节,还剩2字节
double c; // 8 double无法存储,再次开辟8字节
} D, *DP;
int main()
{
printf("%ld",sizeof(D));//结构体大小就为开辟的8+8=16字节
}
为什么要进行字节对齐?
1. 平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。(提高程序的移植性)
2. 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
3. 内存原因:在设计结构体时,通过对齐规则尽可能优化结构体的空间大小至最小空间
六丶结构体总结
1. 不能把结构体变量作为整体引用,只能对结构体变量中各个成员变量分别引用
2. 如果成员变量本身属于另一种结构体类型,用若干个成员运算符一级级找到你想要的成员 变量
2. 如果成员变量本身属于另一种结构体类型,用若干个成员运算符一级级找到你想要的成员 变量
3. 可以把成员变量当成普通变量运算
4. 在数组中,数组之间是不能彼此赋值的,结构体变量可以相互赋值
#include <stdio.h>
struct work
{
int ip;
};
struct student
{
int id;
int age;
struct work w1;
} stu;
int main(int argc, char const *argv[])
{
stu.w1.ip = 10;
return 0;
}