结构体
不同类型数据的集合
数组是相同类型数据的集合
结构体定义语法
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义结构体
struct student {
char name[200];
unsigned int age;
char tel[16];
float scores[3];
char sex;
} stu;//初始化结构体方法四
int main(void)
{
//初始化结构体方法一:
//struct student stu = { "zhangsan",18,"18112345678",100,200,300,'M'};
//初始化结构体方法二:
//struct student stu = { .age = 18, .name="zhangsan",.tel="18112345678",.scores[0]=100,.scores[1]=200,.scores[2]=300,.sex='M'};
//初始化结构体方法三:
//struct student stu;
strcpy(stu.name, "谢允");
stu.age = 18;
strcpy(stu.tel, "18112345678");
stu.scores[0] = 100;
stu.scores[1] = 100;
stu.scores[2] = 100;
stu.sex = 'M';
printf("姓名:%s
", stu.name);
printf("年龄:%u
", stu.age);
printf("电话:%s
", stu.tel);
printf("成绩:%.1f %.1f %.1f
", stu.scores[0],stu.scores[1],stu.scores[2]);
printf("性别:%s
", stu.sex == 'M' ? "男" : "女");
return 0;
}
结构体大小和内存存储结构
//结构体需要根据数据类型进行内存对齐,按最大数据类型分割内存区域
struct student {
char name[20];//20
unsigned int age;//4
char tel[15];//15
float scores[3];//12
char sex;//1
}
计算上述结构内存大小的步骤:
1.上述结构体最大数据类型占4个字节,那么结构体总大小为4的倍数
2.name存储019,age存储2023,tel存储2438(还剩1字节满足4字节倍数,下一元素数据类型占4字节,超过1字节,从下一个4字节开始存储),scores存储4051,sex存储52(补全4字节,实际存储52~55),所以一共存储56字节
存储字节优化
//结构体需要根据数据类型进行内存对齐,按最大数据类型分割内存区域
struct student {
char name[20];//20
unsigned int age;//4
char tel[15];//15
char sex;//1
float scores[3];//12
}
name存储019,age存储2023,tel存储2438(还剩1字节满足4字节倍数,下一元素数据类型占1字节,直接存储,补全4字节),sex存储39,scores存储4051,所以一共存储52字节
#include <string.h>
//结构体需要根据数据类型进行内存对齐,按最大数据类型分割内存区域
struct student {
char name[20];//20
unsigned int age;//4
char tel[15];//16
float scores[3];//24
char sex;//1
} stu;
int main() {
printf("结构体大小:%d
", sizeof(stu));
return 0;
}
结构体数组
struct student stus[2];
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
char name[20];
unsigned int age;
char tel[15];
float scores[3];
char sex;
};
int main(void)
{
struct student stus[2];
for (size_t i = 0; i < 2; i++)
{
printf("请输入:姓名 年龄 电话 成绩 性别
");
scanf("%s %d %s %f %f %f %c", stus[i].name,&stus[i].age,stus[i].tel,&stus[i].scores[0], &stus[i].scores[1], &stus[i].scores[2], &stus[i].sex );
}
for (size_t i = 0; i < 2; i++)
{
printf("姓名:%s
",stus[i].name);
printf("年龄:%u
",stus[i].age);
printf("电话:%s
",stus[i].tel);
printf("分数:%.1f,%.1f,%.1f
",stus[i].scores[0], stus[i].scores[1], stus[i].scores[2] );
printf("性别:%c
", stus[i].sex);
printf("=======================
");
}
return 0;
}
结构体指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu06 {
char* name;
float* scores;
};
int main(void)
{
struct stu06* p = (struct stu06*)malloc(sizeof(struct stu06)*3);
for (size_t i = 0; i < 3; i++)
{
p[i].name = (char*)malloc(sizeof(char) * 21);
p[i].scores = (float*)malloc(sizeof(float) * 3);
scanf("%s %f %f %f", p[i].name, &p[i].scores[0], &p[i].scores[1], &p[i].scores[2]);
}
for (size_t i = 0; i < 3; i++)
{
printf("%s
", p[i].name);
printf("%.1f,%.1f,%.1f
", p[i].scores[0], p[i].scores[1], p[i].scores[2]);
}
for (size_t i = 0; i < 3; i++)
{
free(p[i].name);
free(p[i].scores);
}
free(p);
return 0;
}
结构体和函数
-
结构体作为函数参数
//值传递,函数内部修改不影响外部数据
void func01(struct stu07 s) {
strcpy(s.name, “lisi”);
s.age = 20;
}
//引用传递,函数内部修改在外部也有效
void func02(struct stu07 *s) {
strcpy(s->name, “lisi”);
s->age = 20;
} -
结构体作为返回值
//返回值,函数外部结构体数据复制可访问
struct stu07 func03() {
struct stu07 s;
strcpy(s.name, “lisi”);
s.age = 20;
return s;
}
//返回地址,函数调用完毕后,地址指向的内容已被销毁,函数外部结构体数据无法访问
struct stu07* func04() {
struct stu07 s;
strcpy(s.name, “lisi”);
s.age = 20;
return &s;
}
结构体嵌套
嵌套结构体计算内存时按包括嵌套的所有结构体的最大数据类型做内存对齐
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stra {
int a;//4
double b;//8
char c;//1=24
};
struct strb {
float d;//4
char* e;//4
short f;//2
struct stra abc;//24
};
int main(void)
{
struct strb strbb;
/*strbb.d = 10.0f;
strbb.abc.a = 100;
printf("%d
", strbb.abc.a);*/
printf("%d
", sizeof(struct stra));
printf("%d
", sizeof(struct strb));
return 0;
}
共用体(也叫联合体)
共用体内的数据共用一块内存,内部所有成员变量地址一致,等于整个联合体的地址
共用体大小按最大数据类型对齐
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义共用体
union vars {
double a;
float b;
int c;
short d;
char f;
} var;
int main(void)
{
printf("%d
", sizeof(var));//输出8;var.f改成char f[12]时,输出16
var.a = 100;
var.b = 3.14;
var.c = 66;
printf("%f
", var.a);
printf("%f
", var.b);
printf("%d
", var.c);//只有最后一次赋值的数据是准确的
return 0;
}
枚举
enum 枚举名称{枚举常量};
枚举常量:是整型常量,不能是浮点数,可以是负值,默认初值从0开始,后续常量较前一个常量+1;可以给任意常量赋初值,后续常量依旧较前一个常量+1
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum colors {
red,green=5,blue,black,pink=18,yellow
}clo;
int main(void)
{
int flg = 2;
if (flg == blue) {
printf("blue is 2
");
}
else {
printf("blue is not 2
");
}
printf("yellow=%d
", yellow);//输出19
return 0;
}
typedef
为已有数据类型设置别名
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned long long ull;
struct studentInfoList {
char name[20];
char sex;
};
typedef struct studentInfoList sinfo;
int main(void)
{
ull c = 30;
printf("%d
", c);
sinfo s1;
s1.sex = 'M';
printf("%c
", s1.sex);
return 0;
}