首页 > 其他分享 >C语言进阶(6)

C语言进阶(6)

时间:2024-08-10 22:51:59浏览次数:14  
标签:进阶 struct int C语言 内存 对齐 字节 结构

1.结构体类型的声明和初始化

结构体是一堆数据类型的集合体(与数组不同的是它可以是不同的数据类型)。结构体声明的是一个图纸,并不向内存申请空间,只有在设置变量的时候我们才进行划分空间给变量。结构体的变量数据类型可以理解成struct (结构体名),在初始化时我们就要牢记这个原则。

下面是结构体声明的示例:

struct s
{
	int a;
	char n[3];
};

下面是结构体变量的初始化和建立有两种,第一种优点是简单,缺点是这种变量是全局变量;第二种优点是局部变量,缺点是书写较复杂,推荐第二种。

struct s
{
	int a;
	char n[3];
}h = { 8,"akd" };
struct s
{
	int a;
	char n[3];
};
int main()
{
	struct s f = { 9,"hak" };
	return 0;
}

还有一种特别的声明可以忽略其结构体标签,只能使用上面第一种的形式来初始化变量,还有只能这种结构体使用一次。下面是使用示例

struct
{
	int g;
	short f;
	char d;
}you={9,5,'f'};

还有一种结构体套结构体的形式如下,此外我们还可以在主函数的内部进行声明结构体都可以。注意完全相同的两个不完全声明对于编译器来说是二者类型是完全不同的如下图。

struct
{
	int g;
	short f;
	char d;
	struct s j;
}you = { 9,5,'f',{9,"aas"} };

 

 2.结构体传参

结构体传参有两种形式一种是传值传参,另一种是传址传参;

void test1(struct s g)
{
	;
}
void test2(struct s* p)
{
	;
}
int main()
{

	struct s f = { 9,"hak" };
	test1(f);
	test2(&f);
	return 0;
}

传址传参较传值传参更有优越性,它可以防止函数内存空间占用过多,而传值传参会在函数对于结构体进行一次临时拷贝。

3.结构体的自引用和内存对齐

结构体自引用就是结构体声明内部结构体自己引用自己,在我们还要设置一定的限制条件否则会形成死循环。结构体自引用在形式上非常像函数递归。示例如下

struct d
{
	int b;
	struct d* next;
};

上面中结构体中又引用自己,添加了指针作为限制条件防止出现死循环。

结构体的内存对齐与结构体在内存中的存储有关。

结构体存在一个结构体变量偏移量,结构体在内存中开辟一片空间这一片空间是第一个字节的内存偏移量是0,第二个是1,后面以此类推。对齐数就是默认对齐数和数据类型大小的较小值(如果没有默认对齐数直接就是数据类型大小)。在存储时,不同数据结构体成员只能存储在它对应的对齐数的整数倍的内存偏移量上,以此为起点向后存储几个字节。结构体里面有结构体情况下,我们计算的对齐数是这个结构体那么最大对齐数,然后我们按照普通结构体成员进行对待就行。存储结构体是从上到下。结构体的数据大小是这个结构体最大对齐数的整数倍。

struct d
{
	char a;
	int b;
	char c[10];
};

对于上面那个结构体而言,对于a对齐数是1占偏移量为0的字节,对于b由于对齐数为4,所以占用偏移量为4~7的字节,对于c对齐数为1,所以占用的是8~17的字节,整个结构体最大对齐数为4,所以这个结构体占用为20个字节。

看看输出结果是

内存对齐优点:1. 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特 定类型的数据,否则抛出硬件异常。

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

总体来说: 结构体的内存对齐是拿空间来换取时间的做法。 

那么我们为了使用更加节省空间,我们可以将小字节的类型放在前面。

我们还可以修改默认对齐数使用#program pack(默认对齐数),括号那么填写默认对齐数就行,使用完要用#program pack()回到默认对齐数。

4.位段

位段定义时与结构体类似,但是位段里面只能有整形家族的数据类型,还有在位段里面每一个数据类型都是 int a:7的形式。下面是使用示例

struct g
{
	int h : 7;
	int v : 8;
};

h后面的数字代表了h开辟的内存大小是多少比特,不能超过最大int整形数所占用的字节。

位段在内存 中存储时先开辟一个字节,然后更据h所占用情况和编译器不同环境,决定是否要进行在一个字节内部是从左至右还是从右至左;决定当一个字节有空位时不满足下一个成员是否要先填充这个字节然后再填充下一个字节还是直接进行下一个字节。

位段有其本身的优点时可以将内存空间大大省略,缺点是跨平台问题,一个代码在不同平台有不同的解释,造成困难。

5.枚举常量

枚举常量是一个常量将一个以此命名的变量规范了他的取值范围,在枚举常量成员中每一个都有自己的编号,默认第一个是0,第二个是1,后面以此类推(我们可以修改第一个,达到修改整体的效果,我们还可以修改每一个,达到赋值效果)。只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。下面是使用示例:

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

 6.联合体(共用体)

联合体就是一个空间,联合体里面成员大家都可以使用这个空间假如int a和char b是共用体成员,int a是4个字节,char b就占用了int a第一个字节(低地址),下面是使用示例

union po
{
	char a;
	int b;
};
int main()
{
	union po gh;
	return 0;
}

联合体的存储空间至少大于最大空间字节数,当最大字节数不等于对齐数的整数倍时,空间就是对齐数的整数倍。

上面的开辟空间数是4个字节。

 

标签:进阶,struct,int,C语言,内存,对齐,字节,结构
From: https://blog.csdn.net/2401_86372508/article/details/141095230

相关文章

  • Midjourney进阶-创建与管理自己的专属参数
    ​前言/introduction如题,这篇我们要学会创建与管理自己的专属参数。这里的参数指的是提示词尾缀添加的用于控制图片生成尺寸、模型、风格等参数,如:--ar+空格+数值,--s+控股+数值/preferoptionset(创建专属参数)用途:创建一个专属参数,也就是自己设定一个符号来代表(代替......
  • 【C语言】字符函数和字符串函数
    目录一、字符函数(1)字符分类函数(2)字符转换函数二、字符串函数(1)strlen①函数原型②注意事项③模拟实现函数(2)strcpy①函数原型②注意事项③模拟实现函数(3)strcat①函数原型②注意事项③模拟实现函数(4)strcmp①函数原型②模拟实现函数(5)strncpy①函......
  • 堆总结(C语言)
    堆总结(C语言)二叉树的顺序结构及实现堆是什么堆的分类堆的实现堆的向下调整堆的向上调整堆的应用堆排序TOP-K问题思路:堆是什么堆总是一棵完全二叉树,堆是用来存完全二叉树的,如果存普通的二叉树就会浪费空间。堆(一种二叉树)使用顺序结构的数组来存储。堆不是简单的......
  • 【时时三省】(C语言基础)操作符3
    山不在高,有仙则名。水不在深,有龙则灵。             ----CSDN时时三省&取地址操作符示例: 每个内存单元都有自己的编号编号就成为内存单元的地址&a就是找出a的地址后面可以加一个int*pa=&a是可以用来存放地址pa是用来存放地址的-pa就是一......
  • 初识c语言
    什么是c语言c语言是一门计算机编程语言,可广泛用于底层开发。c语言是一种能以简易方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。第一个c语言程序入门第一个c语言代码如下:那么其运行的结果就是打印helloworld,运行结果如下:......
  • 【C语言(谭浩强)】程序设计与 C 语言
    博客主页:小蜗系列专栏:C语言(谭浩强)版关注博主,后期持续更新系列文章如果有错误请大家批评指出,我会及时修改感谢大家点赞......
  • C语言----结构体
    结构体结构体的含义自定义的数据类型它是由很多的数据组合成的一个整体,结构型数据其中的每一个数据,都是结构体的成员书写的位置:函数的里面:局部位置,只能再本函数中使用函数的外面:全局位置,在所有的函数中都可以使用#include<stdio.h>#include<string.h>structm......
  • C语言指针变量详解(函数指针,函数指针数组,转移表)
    指针变量 1.字符指针变量在指针的类型中我们知道有⼀种指针类型为字符指针char*;⼀般使⽤:intmain(){charch='w';char*pc=&ch;*pc='w';return0;}还有⼀种使⽤⽅式如下:intmain(){const......
  • C语言指针与数组详解(指针数组,数组指针,⼆级指针)
    指针与数组1.数组名的理解1.1结论:数组名是数组⾸元素的地址,但是有2个例外。      •sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩     •&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数......
  • C语言制作一个简易的猜拳小游戏
    用c语言制作一个简易的猜拳小游戏 ,如果跳出错误在getch()上可以改成_getch()试试即可,新版本vs可能认为getch()是不安全的所以不让用。如果需要有图像的小游戏的话导入easyx,把输出语句修改成画图即可编程画图,记得修改图片位置哦 以下是完整代码,直接CV即可main.c #includ......