由sizeof 这个“管”,窥一窥C语言这只“豹”

在C语言开发中,sizeof()是一个什么样的存在呢?有多少人认为它是个函数?或者曾经是否也认为它是函数呢?

今天我们介绍下sizeof()的同时,并通过它延伸展开,来聊一聊一些C语言的基础知识。

1、sizeof是什么?

sizeof是C语言中的关键字,也可以认为是一种运算符。 是一个判断数据类型或者表达式长度的运算符。

2、sizeof的使用及C语言知识延伸

通过实际的代码编写并使用printf();函数来输出要展示的结果,来向大家详细进行说明。(编辑编译环境 :C FREE-5)

1)测试基本数据类型的长度

#include #define uint8_t unsigned char #define uint32_t unsigned intint main(void){ //基本数据类型 printf("uint8_t length = %d\r\n",sizeof(uint8_t));printf("\r\n");printf("uint32_t length = %d\r\n",sizeof(uint32_t));}

通过编译输出如下内容:

可以看出uint8_t 类型占用1个字节 。uint32_t 类型占用4个字节。没毛病,咱们继续。

2)测试普通变量的数据长度

#include #define uint8_t unsigned char #define uint32_t unsigned intuint32_t Var ;//普通变量 int main(void){  //普通变量 printf("Var length = %d\r\n",sizeof(Var));printf("\r\n");}

通过编译输出如下内容:

我在代码中定义了一个uint32_t 类型的变量,毫无悬念,这个变量也占4个字节。继续往下看:

3)测试数组的数据长度

#include #define uint8_t unsigned char #define uint32_t unsigned intuint32_t Array_A[10];//普通数组 int main(void){ //普通数组 printf("Array_A length = %d\r\n",sizeof(Array_A));printf("\r\n");printf("Array_A[10] length = %d\r\n",sizeof(Array_A[10])); printf("\r\n");printf("&Array_A length = %d\r\n",sizeof(&Array_A));printf("\r\n");printf("&Array_A[0] length = %d\r\n",sizeof(&Array_A[0]));printf("\r\n");}

通过编译输出如下内容:

这里我重点说下,通过测试我们可以看到:

sizeof()的括号中,直接写数组的名字,则求的是整个数组所占用的字节数。

sizeof()的括号中,写入Array_A[10],居然也可以等于4,因为Array_A[10]这个数组定义的是uint32类型的,从Array_A[0]到Array_A[9],所以任何一个元素都是4字节,但是Array_A[10]这个元素下标到10了,明显溢出。软件居然没有报错,甚至都没有警告。这个地方要注意一下。

sizeof()的括号中,写入&Array_A,代表数组首地址,占用4个字节。

sizeof()的括号中,写入&Array_A[0],代表数组首元素地址,也占用占用4个字节。

4)测试指针变量的数据长度

#include #define uint8_t unsigned char #define uint32_t unsigned intuint32_t Var ;//普通变量 uint32_t *p = &Var;//指针 int main(void){ //指针 printf("p length = %d\r\n",sizeof(&p));printf("\r\n");printf("*p length = %d\r\n",sizeof(*p));printf(" \r\n");}

通过编译输出如下内容:

为什么&p的长度和*p的长度都是4个字节呢?

“printf("p length = %d\r\n",sizeof(&p));”这一条输出指针地址的长度。是4个字节。

“printf("*p length = %d\r\n",sizeof(*p));”这一条输出的是指针所指向变量类型的长度。也就是这句话:“uint32 *p = &Var" 从上面我们可以得知Var的数据类型就是uint32_t,也是4个字节。

好,下面我们来稍微做个更改:

#include #define uint8_t unsigned char #define uint32_t unsigned intuint8_t Var ;//普通变量 uint8_t *p = &Var;//指针 int main(void){ //指针 printf("p length = %d\r\n",sizeof(&p));printf("\r\n");printf("*p length = %d\r\n",sizeof(*p));printf("\r\n");}

这这里我把 Var的数据类型由uint32_t 改为uint8_t ,把uint32_t *p 改为 uint8_t *p。然后大家可以思考一下:

 “printf("p length = %d\r\n",sizeof(&p)); “输出多少?

“printf("*p length = %d\r\n",sizeof(*p));”输出多少?

下面我们来看结果:

由编译结果可以看到,&p的长度是4。是4个字节吗?和你想得一样吗?这个结果对吗?我们不是把uint32_t *p 改为 uint8_t *p了吗?不应该是1个字节吗?

这里引伸出一个重要的结论: *号前面的数据类型只是表示指针所指向的内存里数据的类型,并不代表指针地址的类型。它和指针的大小无关,并不会对指针的长度产生影响。指针的地址大小是和所处的编译环境有关系。 

*p的长度,这里编译结构现实变成了1个字节。因为指针指向的数据类型改成了uint8_t ,也就是Var变量变成了1.因为Var 的数据类型是 uint8_t ,所以对应的*p前面的数据类型也要是uint8_t,  这样才能保持一致,否则编译器会提示不兼容。这也从侧面应证了: *号前面的数据类型只是表示指针所指向的内存里数据的类型,并不代表指针地址的类型。”  

这个内容就说到这里,感兴趣的朋友可以在自己的编译环境上测试一下。

5)测试构造数据类型的数据长度

#include #define uint8_t unsigned char #define uint32_t unsigned inttypedef struct{uint8_t Var1;uint8_t Var2;uint32_t Var3;}ST_Test; typedef union{ ST_Test st_test;uint8_t Array_B[10];}UN_Test;int main(void){ //构造数据类型 printf("ST_Test length = %d\r\n",sizeof(ST_Test));printf("\r\n");printf("UN_Test length= %d\r\n",sizeof(UN_Test));printf("\r\n");}

通过编译输出如下内容:

我们接着来看,首先第一个构造的数据类型是一个结构体:根据编译输出的提示,该结构体占用的长度为8个字节。为什么是8个字节,不是6个字节?在结构体中,数据长度不是单纯的相加,而是会涉及到字节对齐的问题。网上有很多这方面的资料,这里不深入展开了。

第二个构造的数据类型是共用体。共用体和结构体的最大区别就是内部的各个成员变量共用一块内存。内存大小取决于成员变量中最大的成员。那按道理这个共用体的长度应该是10呀。因为共用体内的两个成员,结构体成员是8个字节,Array_B[10]是10个字节。为什么是12呢?同理,也是字节对齐的原因。

然后接着再做一个延伸:

#include #define uint8_t unsigned char #define uint32_t unsigned inttypedef struct{uint8_t Var1;uint8_t Var2;uint32_t Var3;}ST_Test;#pragma pack(1)typedef union{ ST_Test st_test;uint8_t Array_B[10];}UN_Test;#pragma pack()int main(void){ //构造数据类型 printf("ST_Test length = %d\r\n",sizeof(ST_Test));printf("\r\n");printf("UN_Test length= %d\r\n",sizeof(UN_Test));printf("\r\n");}

编译输出为:

通过使共用体一字节对齐后,可以看到它的数据类型占用的内存大小就变成了10个字节。

共用体可以用来测试数据存储模式是大端模式还是小端模式。限于篇幅,这里就不展开了。感兴趣的朋友自行百度。

这就是今天要分享的内容,比较基础。给不清楚这块知识的朋友提供个思路。明白了这块的朋友也可以借此机会复习一下。说得不对的地方,还请各位朋友提出宝贵意见。一起学习,共同进步一直是本号的宗旨之一。 

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 1
收藏 2
关注 29
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧