【C语言】如何正确使用sizeof

article/2025/8/27 16:51:55

sizeof用过吧?你肯定用过,至少你刚开始学C或者C++的时候,学到类型这一节,你一定会写如下代码测试每个类型的长度。

  printf("%d", sizeof(int));printf("%d", sizeof(char));printf("%d", sizeof(short));printf("%d", sizeof(long));printf("%d", sizeof(float));printf("%d", sizeof(double));

对,这就是sizeof的作用,它就是用来查询对象或类型的大小的。

下面详细说一下它的具体使用方式

测试环境:vs2015(win32 debug) win10-64

一、sizeof的具体使用

sizeof是用来查询对象或类型的大小,也就是说,查看某一个类型或对象它在内存中占几个字节。

它的使用方式有如下两种

sizeof(类型) 
sizeof 一元表达式

很多人看到sizeof后面的括号,就把sizeof当成是一个函数,事实上并不是,它是C语言中的一个运算符

具体使用的时候,sizeof后面是否需要有括号,那要看你测试的是类型,还是表达式。

举例,如果你测试的是类型的话,比如要测试int,char或者一个结构,那就必须要使用括号,例如

struct  sss
{int x;int y;
};
int main()
{printf("%d", sizeof(int));printf("%d", sizeof(struct sss));return 0;
}

结构也是一种类型,这样的就必须要套括号,如果不套,就会报语法错误

但是表达式不需要一定写括号,当然,也可以写括号,例如

 int a[] = { 1,2,3,4,5 };printf("%d\n", sizeof a);printf("%d\n", sizeof(a));

上面代码都可以,因为a不是类型,所以后面的括号,可写可不写

说到sizeof测试表达式,有一个地方需要注意,sizeof的优先级,在C的运算符中级别较高,
在这里插入图片描述
在这个级别中,结合方式是从右到左的方式,所以,以下代码

int c = 1;
int v = sizeof c+1 ;

最终v的值是5,而不是4,应为sizeof的运算优先级大于加号,所以,首先计算了sizeof c,然后又加了一个1,上述代码,相当于以下代码

int c = 1;
int v = sizeof(c)+1 ;

所以,你要想测试类似c+1,这种表达式,需要给他套括号,不过上述代码测试可能没有意义,c+1还是int,测试出来和c一样,还是4

有一点需要主要,sizeof是测试类型的,其他的不能测试,比如函数,void,都不行,但是void*,和函数指针可以,因为void*和函数指针都是指针类型,指针类型是可以测试的,代码如下

int main()
{int v = sizeof(void*) ;int(*fp)(int a);v = sizeof(fp);return 0;
}

返回的都是4

二、深入一下sizeof

上面已经说到,sizeof它不是个函数,只是个运算符,只是用了一个英文名字,没有用符号表示。既然不是函数,也就不存在运行时调用的问题,也就是说,sizeof的值,是在你运行编译程序时,就已经确认的,看以下代码,来说明这个问题

int main(int g)
{int c = 1;int v = sizeof(c)+g ;return 0;
}

因为c是个int所以,v的值应该是4+g的最终结果。看汇编代码
在这里插入图片描述
可以看到,g的值被存入了eax,然后把eax加了4,这个4就是sizeof©,测试出来的值。sizeof这个运算符根本没有参与程序运行相关的任何操作,程序在编译时就直接判断出sizeof的值是4

所以说,如果你要跨文件测试sizeof的话,有些类型,没法搞,例如,在不同文件中有

//b.c
#include <stdio.h>
int xxx[] = { 1,2,3,4,5 };
//a.c
int main()
{extern int xxx[];printf("%d\n", sizeof(xxx));return 0;
}

上述文件,不用编译,VS就直接提示错误了
在这里插入图片描述
这就是不完整类型,和不能测试VOID是一个道理,这就是最开始说的,sizeof在编译前就确定了要测试的类型大小,所以你测试的sizeof一定是要能确认的才行

再说一点,sizeof在用于测试数组或者结构的时候,会返回它实际的占用大小,例如

struct  sss
{int a;void* b;
};int main()
{int a[] = { 1,2,3,4,5 };printf("%d\n", sizeof(a));printf("%d\n", sizeof(struct sss));return 0;
}

上述代码返回20,8

因为sss里,int和void*都是4,共占8,a是5个int,共占20

还有一点,看下列代码

void fun(int a[])
{printf("%d\n", sizeof(a));
}
int main()
{int a[] = { 1,2,3,4,5 };printf("%d\n", sizeof(a));fun(a);return 0;
}

上述代码会输出
在这里插入图片描述
不要奇怪,虽然看上去调用fun(a)的时候,是把a传入了fun中,但实际上,编译器并非传入了数组,而是传入了指向这个数组的指针int *a ,指针的长度就是4

上述代码相当于下面的代码

void fun(int * a)
{printf("%d\n", sizeof(a));
}
int main()
{int a[] = { 1,2,3,4,5 };fun(a);return 0;
}

再看一个

struct  sss
{int a;char b;
};int main()
{printf("%d\n", sizeof(struct sss));return 0;
}

sss中,a是int 占4,b是char 占用1

但上面程序最终输出是:8

知道为什么吗?这是另一个问题,其实和sizeof本身没关系,以后会说


http://chatgpt.dhexx.cn/article/OKyasIeA.shtml

相关文章

Sizeof的用法;他是一个函数吗?

1.一直以来以为sizeof是一个函数&#xff0c;看过c语言深度剖析才知道&#xff0c;sizeof是一个骗子&#xff0c;它伪装的很好~~~ 以下我们用实际代码来告诉你它其实是 关键字 #include<stdio.h> int main() { int i 0; printf("%d %d %d\n",sizeof(int)…

c语言—常见字符串函数与sizeof详解

1.sizeof使用 a.代码1 int main() {int a 0;int arr[] { 1,2,3,4 };printf("%d\n", sizeof(a));printf("%d\n", sizeof a);printf("%d\n", sizeof(&a));//表示地址的大小printf("%d\n", sizeof(int));printf("%d\n"…

sizeof函数的用法

sizeof函数的用法&#xff1a; 1、sizeof()函数是用来计算变量所占内存空间的大小&#xff0c;单位是字节&#xff08;byte&#xff09; 举例如下&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include <stdio.h>//sizeof函数的用法 //sizeof()函数是用来计算变量所占…

C/C++ | sizeof()函数

C语言中 判断数据类型长度符的关键字 用法 sizeof (类型说明符) sizeof 表达式 定义 sizeof是C/C中的一个操作符&#xff08;operator&#xff09;&#xff0c;简单的说其作用就是返回一个对象或者类型所占的内存字节数。 MSDN上的解释为&#xff1a; The sizeof keyword…

开发人员必知!什么是Scrum敏捷开发?

什么是Scrum敏捷开发 Scrum是敏捷开发的一种,是一种以人为本,迭代式增量软件开发的过程,以英式橄榄球争球队形(Scrum)为名,因此可以想象,整个团队是高效而富有激情的。以人为本,即Scrum开发特别强调沟通,要求团队所有人员都坐着一起工作,通过高效的沟通解决问题。 S…

Scrum敏捷开发框架

Scrum 是一个用于开发和维持复杂产品的框架 &#xff0c;是一个增量的、迭代的开发过程。在这个框架中&#xff0c;整个开发过程由若干个短的迭代周期组成&#xff0c;一个短的迭代周期称为一个Sprint&#xff0c;每个Sprint的建议长度是2到4周(互联网产品研发可以使用1周的Spr…

Scrum敏捷开发实战分享(上篇):方法介绍、敏捷团队和敏捷流程

一、方法介绍 先从一则故事说起&#xff1a; 一天&#xff0c;一头猪和一只鸡在路上散步 鸡对猪说&#xff1a;“嘿&#xff0c;伙计&#xff0c;我们合伙开一家餐馆怎么样&#xff1f;” 猪看了一下鸡说&#xff1a;“好主意&#xff0c;那我们给它取什么名字呢&#xff…

什么是Scrum敏捷开发?

什么是敏捷开发&#xff1f; 敏捷开发(Agile Development)是一种以人为核心、迭代、循序渐进的开发方法。 怎么理解呢&#xff1f;首先&#xff0c;我们要理解它不是一门技术&#xff0c;它是一种开发方法&#xff0c;也就是一种软件开发的流程&#xff0c;它会指导我们用规定…

Scrum敏捷开发基础知识篇

Scrum 的定义 Scrum ( 名词): Scrum 是一个框架&#xff0c;在此框架中人们可以解决复杂的自适应难题&#xff0c;同 时也能高效并创造性地交付可能最高价值的产品。 Scrum 是: • 轻量的 • 易于理解的 • 难以精通的 Scrum 是一个框架&#xff0c;自上世纪 90 年代初以来&…

小团队SCRUM敏捷开发项目管理

概述 单团队敏捷开发主要是针对10人以下、只有一个Scrum团队的小型产品或项目的敏捷开发。 对于小型团队来说&#xff0c;在Leangoo中创建一个单团队敏捷开发项目就可以很好地支持团队产品或项目的开发。 适用场景 适用于单个团队进行Scrum敏捷开发协作&#xff0c;Leangoo项目…

实施Scrum敏捷开发的关键要素

一、敏捷开发由来 2001年2月11日至13日&#xff0c;美国犹他州瓦萨奇山雪鸟滑雪胜地&#xff0c;17个人聚到一起&#xff0c;试图找到软件开发的共识&#xff0c;最终的成果就是《敏捷软件开发宣言》。参会者们包括来自于极限编程、Scrum、DSDM、自适应软件开发、水晶系列、特征…

SCRUM敏捷开发教程

大家好&#xff0c;我是煎饼哥&#xff0c;本期向大家介绍一个关于敏捷开发的方法&#xff0c;叫做scrum&#xff0c;相信资深的产品经理都接触过类似的项目管理方法。 scrum敏捷开发&#xff0c;是一个美国统计学教授记录了多年工作经验&#xff0c;总结出来的一套简单易懂的开…

Scrum敏捷开发模式

前言 我的个人博客 最近报名参加了微信小程序应用开发赛&#xff0c;也是作为走向职场前的一次锻炼&#xff0c;为了模拟企业开发的流程&#xff0c;我们团队决定使用敏捷开发模式来管理项目。这篇文章&#xff0c;是对在近些天来网上学习到的Scrum敏捷开发模式的总结。 软件…

无向图的邻接表

如何根据无向图画出邻接表呢&#xff1f; 比如&#xff1a; 第一排的v1&#xff0c;与v2和v4相连&#xff0c;因此两个黄色方框内的数字分别代表v2和v4的下标&#xff1b; 第二排的v2&#xff0c;与v1、v3和v5相连&#xff0c;因此三个绿色方框内的数字分别代表v1和v3和v5的…

C++实现的邻接表

1. 在学习图的存储方式中&#xff0c;邻接矩阵和邻接表是两种比较常用的存储图的方式&#xff0c;下面使用的是C语言实现的邻接表 2. 具体的实现过程如下&#xff1a; ① 首先使用结构体声明图的结构体&#xff0c;图中顶点的结构体&#xff0c;以及指向下一条边的结构体&…

图的存储--邻接表

邻接表既适用于存储无向图&#xff0c;也适用于存储有向图。邻接表常用于稀疏图的存储。 邻接表存储图主要在于将图的各顶点建立一个链表&#xff0c;链表记录该顶点的邻接点的在数组的位置。 #define MAX_VERTEX_NUM 10 // 最大顶点数 #define INF 32767 // 不邻接 typedef…

有向图的邻接矩阵、邻接表和逆邻接表

1、如何根据有向图画出邻接矩阵&#xff1f; 如图&#xff1a; v1指向v2和v3&#xff0c;在矩阵中v1指向v2、v3的表示标1。 注意&#xff1a; v1指向v2在矩阵中是用竖列的v1对应横行的v2 2、如何根据有向图画出邻接表呢&#xff1f; 注意&#xff1a; 画有向图的邻接表时…

【数据结构】 图的邻接表

邻接表是图的另一种存储结构&#xff08;使用链表的思想&#xff09;。 该方式的基本思路&#xff1a;顶点表后指向邻接表&#xff0c;邻接表中依次为当前顶点的邻接点 准备工作 与邻接矩阵类似&#xff0c;在构造邻接表之前&#xff0c;需要存储各个顶点的信息&#xff0c;…

《数据结构》-图的邻接表表示法(四)

邻接表表示法(链式) 存储定义&#xff1a; 顶点&#xff1a;按编号顺序将顶点数据存储在一维数组中关联同一顶点的边(以顶点为尾的弧)&#xff1a;用线性链表存储 无向图的邻接表 例如&#xff0c;如下无向图 则它的邻接表为 无向图邻接表的特点&#xff1a; 邻接表不唯一…

【图】邻接表

目录 无向图的邻接表 链表&#xff08;存相邻顶点下标&#xff09;的类 数组里放的顶点 邻接表&#xff08;操作&#xff09; 构造和析构&#xff08;创建销毁邻接表&#xff09; 插入顶点 插入边 获取下标 插v1、v2之间的边 删除顶点 删除边 输出&#xff1a; 其他…