IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言】_11.自定义类型 -> 正文阅读

[C++知识库]【C语言】_11.自定义类型

正文:

1、结构体

1.1 结构体的基础知识

1.2 结构体的声明

基本知识详见C语言专栏结构体基本知识框架构建,链接:http://t.csdn.cn/5nSzY?

1.3 结构体的特殊声明

(1)在声明结构体时,可以进行不完全声明。

比如匿名结构体类型:

struct 
{
	char name[20];
	char id[12];
}ss;

(2)如果两个及以上匿名结构体成员相同,在编译器看来也是不同类型的结构体。

比如:

struct
{
 int a;
 char b;
 float c;
 }x;

struct
{
 int a;
 char b;
 float c; 
}a[20], *p;

在这两个匿名结构体中,p≠&x;

1.3 结构体的自引用

#include<stdio.h>
struct Node
{
	int data;      //数据域
	struct Node* next;  //指针域
};
int main()
{
	struct Node n;

	return 0;
}

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

示例一:

#include<stdio.h>
struct Point
{
	int x;
	int y;
}p1={1,2};       //定义结构体变量p1同时进行初始化
struct Point p2 = { 3,4 };    //定义全局变量p2并初始化
int main()
{
	struct Point p3 = { 5,6 };         //定义局部变量p3并初始化
	return 0;
}

示例二:

#include<stdio.h>
struct Book
{
	char name[20];
	float price;
	char id[12];
}s1={"xxxxx",55.5f,"C001"};
struct Node
{
	struct Book b;
	struct Node* next;
};
int main()
{
	struct Book s2 = { "xxxx",60.7f,"C002" };
	struct Node n = { {"xxx",49.2,"C003"},NULL};
	return 0;
}

1.5 结构体内存对齐

运行如下代码,代码及运行结果截图如下:

?可以发现同样变量的结构体阿紫变量顺序不同的情况下所占内存不同。

接下来介绍计算结构体大小时存在的一个问题:结构体内存对齐。

(1)结构体的对齐规则:

1. 第一个成员在与结构体变量偏移量为0的地址处。? ? ?
ps:偏移量是指相对于起始位置的字节数。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数与该成员大小的较小值
ps:VS编译器默认对齐数是8
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
接下来图示s1 和s2结构体的内存占用情况:
s1:

?s2:

在C语言中,定义offsetof宏用于判断结构体成员相对于起始位置的偏移量。在此处我们可以用于验证:

代码编写及运行结果截图如下:

?ps:offsetof宏部分相关知识如下:(来源:Cplusplus.com)

? 再举一例嵌套的情况:

分析结构体S3容易得知:double类型为8个字节,char类型为1个字节,int类型为4个字节,结构体总大小为16个字节。此处不再做详细解释。

由第四条规则可以知道,在S3中,最大对齐数为8,在S4结构体char占0位置后,S3对齐在8位置,S3占用16个字节,此时偏移量为23,再加上double后,最后偏移量为31,总共占字节为32。结构体的大小就是所有最大对齐数(1、4、8)的整数倍,也就是32。

ps:编译器默认对齐数:

VS默认对齐数是8,Linux环境下没有默认对齐数(自身大小就是对齐数)

(2)内存对齐的原因:

① 平台原因:不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常;

②性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐:为了访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存仅需要一次访问。

以上例S1为例,在32位机器上,一次操作4个字节,如果不不对齐的话,则需要访问两次才能读取成员i,但是如果对齐,则一次可以读取完毕。

总体来说,结构体的内存是用空间换时间的方法。

(3)基于结构内存对齐而得到的结构体书写启发:

让占用空间小的成员尽可能地集中在一起。

比如同等效果的结构体S1和S2,我们采用S2的成员顺序就可以节省空间。

1.6 修改默认对齐数

在上例代码中,将默认对齐数8改为4,则在c占用0位置时,d不再对齐至8位,而是第4位,从而内存变为12个字节。?

当默认对齐数为1时,即不对齐,可以最大程度节省空间。

1.7 结构体传参

在结构体传参时,尽量采取传址,这样更节省空间且效率更高。

示例:

#include<stdio.h>
struct S
{
	int arr[1000];
	int num;
};
void print1(struct S s)
{
	printf("%d\n", s.num);
}
void print2(struct S* s)
{
	printf("%d\n", s->num);
}
struct S s = { {1,2,3,4},1000 };
int main()
{
	print1(s);
	print2(&s);
	return 0;
}

详细知识详见C语言专栏结构体基本知识框架构建,链接:http://t.csdn.cn/5nSzY?

2、位段

2.1 位段的概念

位段和结构非常相似,其声明也与结构体的声明非常相似,有两个不同:

(1)位段的成员必须是 int ,unsigned int 和signed int ;

(2)位段的成员名后面有一个冒号和一个数字。

struct A     //A就是一个位段类型
{
	int _a : 2;      //表示_a这个成员占2个bit位
	int _b : 5;
};

?在实际应用中,当我们构造结构体时,部分成员变量的取值范围并不需要扩大到1个整型时,我们可以通过限制bit位来节省空间。比如上例中的int _a:2,如果我们需要的_a变量只需要0 1 2 3四个值,那么赋予其int型会浪费很大的空间,此时就可以使用位段方式节省空间。

2.2 位段的内存分配

(1)位段的成员可以是int , unsigned int , signed int , char等;

(2)位段的空间是按照需要以4字节(int)或1字节(char)进行开辟的;

(3)位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段或针对位段写可跨平台的代码;

我们首先假设一种内存分配模式:先使用低位bit位,如果高位不足时做剩余处理,开辟新字节使用

?进行计算后,与vs调试内存监视进行比较,发现内存分配确实如此。

2.3 位段的跨平台问题

(1)int 位段被当做有符号还是无符号处理是不确定的;

(2)位段中最大位的数目不能确定:

在早期16位机器上,sizeof(int)占2个字节;在32位机器上,sizeof(int)占4个字节。

故而上例中int d:30;其实在早期机器上便无法运行。

(3)位段中的成员在内存中从左向右还是从右向左分配标准尚未定义;

(4)当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段余位时,是舍弃余位另行开辟还是余位利用,标准尚未规定;

3、枚举

2.1 枚举类型的定义

enum Sex
{
	MALE,
	FEMALE,
	SECRET
};
int main()
{
	enum Sex s = MALE;
	enum Sex s2 = FEMALE;
	return 0;
}

枚举的内容是有数字编号的,从1开始递增:

?也可以进行赋值,被赋值的输出赋值的数值,未被赋值的逐个递增:

?ps:枚举内容被赋值后就是常量,不可再行修改;

?3.2 枚举的优点

(1)增加代码的可读性和可维护性;

(2)和#define定义的标识符比较,枚举有类型检查,更加严谨;

(3)防止命名污染(封装);

(4)便于调试;

(5)使用方便,一次可以定义多个常量;

4.联合(共用体)

4.1 联合类型的定义

union Un
{
char c;
int i;
};
union Un u;

?4.2 联合的特点

联合体的成员是共用一块内存空间的,一个联合体的大小至少是最大成员的大小;

4.3 联合的使用

4.4 计算联合体的大小

(1)联合体的大小至少是最大成员的大小;

(2)当最大成员大小不是最大对齐数的整数倍时,要对齐到最大对齐数的整数倍处;

?

?arr[5]的类型为char,1个字节,int型4个字节,故而最大对齐数为4,arr[5]占用5个字节,i与其共用起始位置的四个字节后,为保证对齐到最大对齐数的整数倍,会再浪费3个字节的空间。

故而该联合体的大小是8;

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 01:47:57  更:2022-09-15 01:49:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 15:34:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码