浅谈~(承上)数据类型(struct\union\enum\数组\void\指针)及其存储

前面两篇我们分别讲了,整型、浮点型,他们的类型以如何在内存中进行存储的。那么这一篇,我们就要开启,C语言中,其他自定义类型,他们在内存中是怎样存储的,占我们多大的内存空间。

(1)数组的大小:

谈到数组,我们不难发现,数组其实上,我们前面几个类型的几何体,当然也不仅仅只有整型,浮点型。

从展现出的数据来看,我们数组,其本质就是一个集合

集齐同一种属性的集合,类似一个封装瓶,在里面只能存放同种性质的东西。 

除开我们常见的char int 类型的数组,这里还涉及到指针数组。(存放指针的数组) 如图arr3,arr4。

注:指针的细节暂时不必讲,在这里各位只需要有这个认识就行~

因此,我们可以得出,数组的大小,其实是类型的大小,在加上数组可存放的个数即可~

(2)枚举类型enum:

在数据类型中,容易被忽略的,就是枚举类型(enum),然而它在实际运用中,又起着不可缺少的作用。 

那enum到底有哪些作用呢? enum和宏定义有什么区别呢? enum的类型的大小,以及enum元素有什么性质呢?

①enum的使用:

具有可阅读性(字描述性),且是相关常量,且区别define具有语法检查~

如图,enum内的有关元素,都是具有相关性的内子。

如图,编译器会自动报错。 

enum定义的格式:

enum tag{


};

enum tag s={0};

②enum和宏定义:

编译器下,对enum以及宏定义的M 进行赋值时会报错。也就得出了一个性质,

enum的元素和宏定义的常量一样,具有常量的属性,不可直接更改。 

③enum的大小以及元素的相关性质:

如图,我们可以清晰地看到:

enum类型的大小占4个字节。而enum内的元素的似乎呈递增趋势。

我们再来看:

这里是负数的例子:

 因此,enum内的元素,

如果你不给它赋值,默认为0。其余元素,会因为第一个元素值的大小,而每次递增1。

(3)结构体类型:

结构体区别于数组,它是一种类型的集合,然而结构体,是多种类型的集合体;

结构体定义:

struct tag{
   int;
   float;
   char;

};

struct tag s={0};

注:关于结构体的使用,即 如何访问结构体内部成员,本篇不会涉及~

①结构体的大小:

按我们惯性思维,结构体s内的元素有2个int 和 1个 char ,加起来该是8字节,但结果却是12,这是为什么呢?

在这里我们要引入一个内存对齐的概念:

我们先画出该结构体类型具体存储的方式后,再来理解内存偏移:

有点小凌乱哈哈哈哈~ 见笑了

规则:

1. 第一个成员在与结构体变量偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8

3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

什么是对齐数如何取值?

 结构体内,最大元素的类型的大小,同编译器(vs)提供的默认值(8)比较,取的较小值。

当然在linux环境下,没有这个概念。

不过,在linux环境下,这个结构体的大小仍然为12。 

认识到了对齐数,也就不难计算这个结构体的大小。

 更多的情况,就留给诸位自行实验

(4)联合体类型:

结构体的定义:

union U{
  int;
  char;
  int;
};

union U u={0};

①联合体类型大小:

 同样,联合体的内存大小计算也并未按我们正常想的那样。4+4+1=9

那,联合体是怎样存储的呢?

我们来看看现象:

我们分别对联合体内的每个成员&。可以发现每个成员的地址都是一样(低地址)。

所以联合体,事实上,是联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小

规则:

①联合的大小至少是最大成员的大小。

②当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

 附:如何更改默认对齐数~

我们能否更改系统默认的对齐数呢?答案是可以的~

#pragma pack(num)

我们可以把上面联合体的改一改:

 结果显然不一样啦~

(5)指针类型:

int* p   //整型指针

char* b //字符型

double* c //双精度型
 
float* d  //单精度

①指针类型的大小:

32位机:

64位机:

 

 可以看出,指针的大小与类型无关,由当前CPU运行模式的寻址位数 决定~

(6)void类型:

void在C语言中被编译器解释为空类型,我们常常在很多地方看到void的应用:

void test()     //函数返回值

void * p        //无类型指针

test(void)      //实参为空

int test(void)  //形参为空

那么void能修饰变量吗?

答案是不能的。

因为在前面定义里说过,创建变量的实质,是在内存上开辟空间。变量的类型,告诉计算机,为它这个 变量开辟多大的空间。 

那么void的大小是多少呢?

vs-2019:

 linux环境下:

这时候void在linux环境下,计算的大小为1,那是否就意味着,在linux环境下,也可以用void来创建变量?

 

答案也是否定。

因此:

不管是linux 还是vs  他们都对void进行的变量命名,是强制不被允许的。 

感谢你的阅读,祝你好运~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值