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

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本身没关系,以后会说

  • 12
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值