赞
踩
一般声明:
struct Book//结构体声明
{
char name[20];
int price;
char id[12];
};
int main()
{
struct Book b1;//是局部变量
return 0;
}
特殊声明:
匿名结构体类型(只能用一次)
//匿名结构体
struct
{
char c;
int i;
char ch;
}s;
//匿名结构体指针
struct
{
char c;
int i;
char ch;
}* ps;
struct Node
{
int d;//4byte
// struct Node n;非法
struct Node* next;//指向下一个同类型的结构体指针
};
#include <stdio.h> struct stu { char name[20]; int age; double score; }s = {"lisi", 20, 100};//结构体声明并定义变量s int main() { struct stu s1 ={"zhangsan", 20, 85};//定义变量s1 struct stu* ps = &s1; //结构体指针ps指向s1的地址 printf("%s %d %lf\n",s.name,s.age,s.score);//一般方式打印结构体成员 printf("%s %d %lf\n",ps->name,ps->age,ps->score);//利用指针打印结构体成员 return 0; }
结果如下:
1.硬件原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对齐的内存访问仅需要一次访问。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值
VScode默认对齐数是8,Linux没有特定的对齐数
1.结构体的第一个成员,放在结构体在内存中存储位置的0偏移处开始
2.从第2个成员往后的所有成员,都要放在一个对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处
3.结构体的总大小是结构体所有成员的对齐数中的最大对齐数的整数倍
4.如果有嵌套结构体,嵌套的结构体对齐到自己最大对齐数的整数倍处,结构体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
//VScode环境下默认对齐数是8 #include <stdio.h> struct S { char c;//1字节 int i;//4字节 }; struct SS { char c1;//1字节 int i;//4字节 char c2;//1字节 }; struct SSS//(相较于SS更节省空间) { char c1;//1字节 char c2;//1字节 int i;//4字节 }; struct SSSS { char c;//1字节 int i;//4字节 double d;//8字节 }; int main() { struct S s = {0}; struct SS s2 = {0}; struct SSS s3 = {0}; struct SSSS s4 = {0}; printf("%d\n", sizeof(s));//8字节 printf("%d\n", sizeof(s2));//12字节 printf("%d\n", sizeof(s3));//8字节 printf("%d\n", sizeof(s4));//16字节 return 0; }
图解如下:
#include <stdio.h>
#pragma pack(2)//预处理:将默认对齐数改为2
struct SS
{
char c1;//1个字节
int i;//4个字节
char c2;//1个字节
};
#pragma pack()//还原默认对齐数
int main()
{
printf("%d", sizeof(struct SS));//打印结果为8
return 0;
}
图解如下:
函数传参时,参数需要压栈,如果传递一个结构体对象时,结构体过大,参数压栈时系统开销比较大,导致性能下降。所以要在结构体传参时,要传结构体的地址。(在结构体初阶中已经讲过了)
位段成员后面有一个冒号和一个数字
struct A
{
//int 4个字节-32bit
int _a:2;//_a成员占2个bit位
int _b:5;//_b成员占5个bit位
int _c:10;//_c成员占10个bit位
//int 4个字节-32bit
int _d:30;//_d成员占30个bit位(最大32bit)
};
位段的长度不能大于存储单元的长度
char型位段<=8bit位
short int型位段<=16bit位
int型位段<=32bit位
long int型位段<=32bit位
//枚举类型的每一项默认递增1,其中的常量可以自定义 #include <stdio.h> enum Color { RED, GREEN, BLUE, Yellow = 5, Purple, Pink }; int main() { printf("%d ", RED); printf("%d ", GREEN); printf("%d ", BLUE); printf("%d ", Yellow); printf("%d ", Purple); printf("%d ", Pink); getchar(); return 0; }
结果如下:
枚举是C语言中一种基本数据类型(不同于其他类型),它可以让数据简洁和易读
1.增加代码的可读性和可维护性
2.和#define定义的标识符比较,枚举有类型检查,更加严谨
3.防止命名污染(封装)
4.便于调试
5.使用方便,一次可以定义多个常量
//以下代码仅供参考 #include <stdio.h> enum Weekday { Mon = 1, Tue, Wed, Thu, Fri, Sat, Sun }; int main() { int input = 0; scanf("输入数字:%d",&input); switch (input) { //case 1: case Mon: printf("Monday"); break; case Tue: printf("Tuesday"); break; case Wed: printf("Wednesday"); break; case Thu: printf("Thursday"); break; case Fri: printf("Friday"); break; case Sat: printf("Satday"); break; case Sun: printf("Sunday"); break; default: printf("input error"); break; } return 0; }
联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间
#include <stdio.h> //联合体的声明 union Un { char c;//1 int i;//4 }; int main() { union Un u;//联合变量的定义 printf("%d\n", sizeof(u));//计算联合变量的大小 printf("%p\n", &u);//打印联合的地址 printf("%p\n", &(u.c)); printf("%p\n", &(u.i)); return 0; }
结果如下:
原理如下:
联合经常用来判断大小端存储
大小端存储:
#include <stdio.h> int check_sys() { union U { char c; int i; }u; int i = 1; return u.c; //返回1 就是小端 //返回0 就是大段 } int main() { int ret = check_sys(); if(ret==1) { printf("小端"); } else { printf("大端"); } return 0; }
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍数。
#include <stdio.h> union Un { char a[5]; int i; }; union un { char b[5]; char c; }; int main() { union Un U; union un u; printf("%d\n", sizeof(U));//结果是8 printf("%d\n", sizeof(u)); //结果是5 return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。