自定义类型(一)
创始人
2025-05-30 19:39:38

文章目录

  • 结构体
  • 结构体内存对齐
  • 结构体传参
  • 位段
  • 枚举

结构体

数组是一组相同类型的元素的集合
结构体也是一些值的集合,结构的每个成员可以是不同类型

声明

struct Book
{char name[20];int price;char id[12];
}b4,b5,b6; //全局变量

特殊声明

//匿名结构体类型
struct
{char c;int i;char ch;double d;
}s;
struct
{char c;int i;char ch;double d;
}*ps;
int main()
{ps = &s;return 0;
}
//编译器会把上面两个自定义结构体类型当成两个完全不同的类型
//所以这是非法的
int main()
{//b1,b2,b3是局部变量2int a;struct Book b1;struct Book b2;struct Book b3;return 0;
}

结构体自引用

//嵌套引用
struct A
{int i;char c;
};
struct B
{int i;struct A c;
};
//错误的自引用格式
struct N
{int d;struct N n;   //err
};
//正确的自引用格式
struct Node
{int data;struct Node* next;  //链表
};typedef struct Node
{int data;struct Node* next;
}Node;

结构体变量的定义和初始化

struct stu
{int age;char i;
};
struct s
{int c;struct stu b;
};
int main()
{struct s d = { 18,{18,'a'} };printf("%d %d %c", d.c, d.b.age, d.b.i);
}

结构体内存对齐

1.结构体的第一个成员,放在结构体变量在内存中存储位置的0偏移处开始
2.从第二个成员往后的所有的成员都放在一个对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处
3.结构体的总大小是所有结构体成员的对齐数中最大的那个对齐数的整数倍

让空间小的变量集中在一起就可以节约一部分空间 修改默认对齐数也可以节约空间
在这里插入图片描述

默认对齐数是可以被修改的

把默认对齐数改为2
#pragma pack(2)
struct s
{char c1;int i;char c2;
};#pragma pack(1) //一般设置2的几次方
struct s
{char c1;int i;char c2;
};
#pragma pack() //取消掉之前设置的默认对齐数2,只有中间的成员默认对齐数为2
int main()
{printf("%zd\n", sizeof(struct s));return 0;
}//宏 offsetof 求相对起始位置的偏移量
#include
struct s
{char c1;int i;char c2;
};
int main()
{printf("%d\n", offsetof(struct s,c1));printf("%d\n", offsetof(struct s,i));printf("%d\n", offsetof(struct s,c2));return 0;
}

结构体传参

结构体传参的时候,要传结构体的地址

位段

什么是位段?
1.位段的成员必须是int、unsigned int或signed int。
2.位段的成员名后边有一个冒号和一个数字。 位段 47 32+15

struct A
{int _a : 2; //_a成员占2个比特位int _b : 5; //_b成员占5个比特位int _c : 10; //_c成员占10个比特位int _d : 30; //_d成员占30个比特位
};

位段的内存分配

1.位段的成员可以是int、unsigned int、signed int或者是char(属于整型家族)类型
2.位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的。
3.位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段
在这里插入图片描述

struct S  
{char a : 3;char b : 4;char c : 5;char d : 4;
};

不跨平台

1.int位段被当成有符号数还是无符号数是不确定的
2.位段中最大位的数目不能确定。(16位机器最大是16,32位机器最大是32,写成27,在16位机器 会出问题)。
3.位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4.当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余 的位还是利用,这是不确定的。 总结 跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在

int main()
{struct S s = { 0 };s.a = 10;s.b = 12;s.c = 3;s.d = 4;return 0;
}

枚举

//枚举顾名思义就是——列举。
//把可能的取值——列举。
//枚举类型的定义
enum Color
{RED=5,//5   //赋初值GREEN, //6BLUE    //7   //自增1
};
//枚举类型的可能取值
//常量
int main()
{//enum Color c = BLUE;printf("%d\n", RED); //0    //5printf("%d\n", GREEN); //1    //6printf("%d\n", BLUE); //2     //7printf("%zd\n", sizeof(RED)); //4return 0;
}

为什么使用枚举?
我们可以使用#define定义常量,为什么非要使用枚举?枚举的优点:
1.增加代码的可读性和可维护性
2.和#define定义的标识符比较枚举有类型检查,更加严谨。
3.防止了命名污染(封装)
4.便于调试
5.使用方便,一次可以定义多个常量。

int input = 0;//枚举类型的使用
enum Option
{exit,mul,sub
};
int main()
{switch (input){case exit:break;case mul:break;case sub:break;}
}

相关内容

热门资讯

三曼村:一个观察中国乡村转型的... 来源:@CGTNGlobalBusiness微博 【三曼...
俄外长:日本正加速军事化 最好... 转自:证券时报人民财讯12月28日电,俄罗斯外长拉夫罗夫在塔斯社28日播发的专访中说,日本领导层最近...
“2025上海台北城市论坛”在... 转自:北京日报客户端以“科技改变生活”为主题的“2025上海台北城市论坛”28日在沪举行。论坛旨在推...
智者勇进•接续奋进新江苏|涟水... 转自:扬子晚报2025 年,涟水县文化广电和旅游局答卷亮点纷呈 —— 省文化艺术政府奖斩获六项大奖,...
最新或2023(历届)新疆养老...  新疆养老保险个人账户查询,  1、电话查询,拨打新疆自治区12333查询热线;  "12333"热...