C语言基础12——结构体2
结构体2
1. 结构体大小
struct student{
char a;
short w;
char y;
int b;
char c;
} stu;
1.1 结构体大小遵循字节对齐原则
字节对齐
在实际使用中,访问特定数据类型变量时需要在特定的内存起始地址进行访问,这就需要各种数据类型按照一定的规则在空间上进行排列,而不是顺序地一个接一个地存放,这就是字节对齐
字节对齐原则
(1)在64位系统下默认的value值为8字节,判断结构体类型中最大成员变量的字节大小,和默认的value值进行比较,按小的数进行对齐
(2)结构体成员进行对齐时遵循地址偏移量是成员类型的整数倍
(3)结构体成员按顺序进行存储,如果不满足以上条件时,需要填充空字节
为什么要进行字节对齐?
(1)平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。(提高程序的移植性)
(2)性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
(3)内存原因:在设计结构体时,通过对齐规则尽可能优化结构体的空间大小至最小空间
【例】
struct student{
char a;
short w;
char y;
int b;
char c;
} stu; // 大小 16
第一步:找出成员变量的大小,让其与编译器的默认的对齐数进行比较,取较小的值作为该成员变量的对齐数
第二步:根据每个成员对应的对齐数画出他们在内存中的相对位置
第三步:计算结构体大小
1.2 结构体数组的大小
sizeof(结构体数组名);
元素个数 * 结构体类型大小
练习1:创建一个结构体数组,数组名为book,结构体成员包含编号,书名,售价(数据类型自己设定)。写一个函数,包含两个形参,分别接收结构体数组的首地址和一个指定的售价,函数的功能为打印结构体数组中售价大于指定售价的书的信息。(参考代码见本文最后)
2. 结构体指针
2.1 概念
2.2 格式
存储类型 数据类型 *指针变量名struct 结构体名 *结构体指针变量名
#include <stdio.h>
#include <string.h>struct student
{int id;int age;
} stu;struct work
{int id;int score;
} w;int main()
{struct student *p1 = &stu;//struct student *p2 = &w; //错误,结构体类型不匹配return 0;
}
2.3 赋值
格式:结构体指针变量 -> 成员变量
-> 指向的
#include <stdio.h>
#include <string.h>struct student
{int id;int age;
} stu;struct work
{int id;int score;
} w;int main(int argc, char const *argv[])
{struct student *p1 = &stu;p1->id = 1;p1->age = 18;printf("%d %d\n", stu.id, stu.age);return 0;
}
(*p1).成员变量
练习2:创建一个结构体数组,数组名为student,成员包含学号,姓名,成绩(数据类型自己设定)从终端输入学生信息,封装函数实现按成绩从低到高打印学生信息。(参考代码见本文最后)
3. 枚举
维基百科的理解:枚举类型用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型。 定义:是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内。
我的理解:枚举类型就是将一些比较固定的值一一列举出来,比如一年有十二个月,一个礼拜有七天,这是毫无疑问的,就可以将这些月份天数用常量来代替。枚举类型和宏定义是差不多的,只有细微区别,宏运行是在预处理阶段完成的,枚举类型是在与编译阶段完成的。
3.1 定义
3.2 格式
enum 枚举名
{
value1,
value2,
value3
...
};
未赋初值时,第一个常数默认是0,后续的常数依次加一(如果第一个值赋值为1,从赋值的1开始递增)
#include <stdio.h>
#include <string.h>enum week
{MON = 1,TUE,WED,Thurs,Fri
};int main(int argc, char const *argv[])
{int day;scanf("%d", &day);switch (day){case MON: printf("Monday"); break;case TUE:printf("Tuesday"); break;case WED:printf("Wednesday"); break;case Thurs:printf("Thursday"); break;case Fri:printf("Friday"); break;default:break;}return 0;
}
4. 共用体
4.1 格式
union 共用体名
{
成员列表;
}
4.2 定义共用体变量
union 共用体名 变量名;
#include <stdio.h>
#include <string.h>union val
{int a;char ch;
} v;int main(int argc, char const *argv[])
{v.a = 10;// 他俩不能同时出现,是以最后一次赋值为准v.ch = 'a';printf("%d\n", v.a);return 0;
}
4.3 特性
- 共用体成员共用同一块地址空间
- 赋值顺序以最后一次为准
- 共用体大小为成员中类型最大的数据的大小
4.4 使用共用体测试大小端
#include <stdio.h>
#include <string.h>union val
{int num;char ch;
} v;int main(int argc, char const *argv[])
{v.num = 0x12345678;if(v.ch == 0x78){printf("小端\n");}else{printf("大端\n");}return 0;
}
------------------------------------------------------这是一条分割线------------------------------------------------------
天才预设的上一篇跳转路径:C语言基础11——结构体1-CSDN博客
天才预设的下一篇跳转路径:完结撒花~
天才预设的合集传送路径:C基础_Gu_shiwww的博客-CSDN博客
参考代码
练习1:
创建一个结构体数组,数组名为book,结构体成员包含编号,书名,售价(数据类型自己设定)。写一个函数,包含两个形参,分别接收结构体数组的首地址和一个指定的售价,函数的功能为打印结构体数组中售价大于指定售价的书的信息。
#include <stdio.h>
#define N 3typedef struct
{int id;char name[32];float price;
} Book;void fun(const Book books[], int size, float t)
{for(int i = 0; i < size; ++i){if(books[i].price > t){printf("%d %s %.1f\n", books[i].id, books[i].name, books[i].price);}}
}int main()
{Book num[N];printf("请输入编号 书名 价格:\n");for(int i = 0 ; i < N ; ++i){ scanf("%d %s %f", &num[i].id, num[i].name, &num[i].price);}float p = 20.0;fun(num, N, p);return 0;
}
练习2:
创建一个结构体数组,数组名为student,成员包含学号,姓名,成绩(数据类型自己设定)从终端输入学生信息,封装函数实现按成绩从低到高打印学生信息。
#include <stdio.h>
#include <string.h>#define N 3struct student
{int id;char name[32];int score;
};void fun(struct student *p)
{struct student temp;for(int i = 0; i < N-1; i++){for(int j = 0; j < N-1-i; j++){if((p+j)->score > (p+j+1)->score){temp = *(p+j);*(p+j) = *(p+j+1);*(p+j+1) = temp;}// if(p[j].score > p[j+1].score)// {// temp = p[j];// p[j] = p[j+1];// p[j+1] = temp;// }}}for(int i = 0; i < N; i++)//printf("%d %s %d\n", p[i].id, p[i].name, p[i].score);printf("%d %s %d\n", (p+i)->id, (p+i)->name, (p+i)->score);
}int main(int argc, char const *argv[])
{struct student stu[N];for (int i = 0; i < N; i++)scanf("%d %s %d", &stu[i].id, stu[i].name, &stu[i].score);fun(stu);return 0;
}