技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> c关键字-sizeof的种种

c关键字-sizeof的种种

浏览:2362次  出处信息

熟悉c的人都知道,sizeof是一个关键字而不是一个宏或者库函数什么的,他的值是在编译时确定的,如果这个不了解,可以现看看这篇文章这篇文章。 既然如此,让我们先看下面几个小例子:

sizeof(int);
sizeof(char);
sizeof(double);

上面三行sizeof的值是多少呢?这里我们假定在32位的x86系统下。我们会得到答案:4,1,8。这个没什么吧,大多数人都应该知道。那么,下面这个:

sizeof(int);
sizeof(long);

在32位x86下,这两个是多少呢?4,8?

实际上,答案是4,4。我们需要注意,long类型在32位系统下是32位的。那么,64位下结果又如何呢?8,8?其实答案是4,8。另一个需要注意的是,64位下的int是32位的

上面只是热热身,现在,让我们看sizeof的下面几种情形:

1、sizeof一个结构体。

这个我就不说啥了,具体的参考这篇文章。至于空的结构体,下面会解释。

2、sizeof数组、指针等 先看下面两个例子:

char a[100];
char b[100]="helloworld!";
char c[]="helloworld!";
char* d=b;
sizeof(a);
sizeof(b);
sizeof(c);
sizeof(d);

在32位x86系统下,以上各是多少呢?

答案是:100,100,12,4。

为什么不是100,12,12,12呢? sizeof一个数组名,返回的是数组的大小,不管你数组里面放的什么数据。所以,第一个数组大小是100,第二个数组大小是100,第三个数组大小是12(别忘记"\0")。第四个呢?第四个不是一个数组名,而是一个指针!32位下指针大小永远是4,不管你是指向一个数组还是一个int还是一个char。 好,这个问题搞清楚之后,看下面这个程序:

int func(char a[100])
{
    printf("%d\n", sizeof(a));
}
int main()
{
    char *m = "helloworld!";
    func(m);
    char n[100]="helloworld!";
    func(n);
}

这个程序会打印出什么结果呢?

答案是:4, 4。 为什么结果都是4?不是应该返回数组长度么?

这里出现又一个需要注意的地方:在作为参数传递的时候,数组名会退化为指针。也就是说,这里的func里的参数,虽然看上去是个数组名,但实际上还是个指针。 你了解了么?下面是几个练习,自己实验下^_^

char *p = NULL;
sizeof(p);
sizeof(*p);
 
int a[100];
sizeof(a);
sizeof(a[100]);
sizeof(&a);
sizeof(&a[0]);

懒得实验?答案分别是4,1,400,4,4,4。为什么?自己想想。

3、sizeof一些诡异的东西

(enum,空类,空struct) 所谓的诡异的东西,就是一些你想到的想不到的东西拿来sizeof。比如说sizeof一个enum类型是多少?一个空struct呢?一个空类呢? 这些诡异的东西在标准C中都没有作出规定,很大程度上都是编译器和系统结构相关的。 先来看一个:

int main()
{
    enum week{Mon, Tue, Wed, Thu, Fri, Sat, Sun};
    printf("%d\n", sizeof(enum week));
}

这个你会得到什么样的结果呢?28? 在gcc或者vc下运行一把,你会得到答案:4。

为什么呢? 实际上,enum具体有多大取决于编译器的实现,目前大多数的编译器都将其实现为int类型。也就是说这里的enum被当作int类型(当然,使用上不一样)。这不是一成不变的,有些编译器,如VC++允许下面这种定义:

//注意这是个cpp文件
enum Color : unsigned char
{
   red, green, blue
};
// assert(sizeof(Color) == 1);

enum先说到这里,那么一个空的结构体是多大呢? 如果你擅长C语言,你可以很快的写出下面的程序:

//this is a *.c file
struct node{
 
}Node;
int main
{
    printf("%d\n", sizeof(Node));
}

很快,你可以验证出来结果是0。 没错,这很好理解。但是,如果你用的是c++呢?

//this is a *.cpp file
struct node{
 
}Node;
 
class node2{
 
}Node2;
 
int main()
{
    printf("%d\n", sizeof(Node));
    printf("%d\n", sizeof(Node2));
}

(不怎么会写c++的我表示压力很大)以上这个c++的例子结果是多少呢?

为什么会得到1,1这个结果呢? 换句话说就是为什么sizeof一个空类和空结构体在c++下就是1呢?

这个原因要追朔到c++标准中的一句话:“no object shall have the same address in memory as any other variable”, 用中国话简单点说就是:不同的对象之间应该有不同的地址(为什么会有这样的规定?看这里)。

既然每个对象都必须有不同的地址,让我们假设上面代码中的Node的size是0,想想会出现什么样的后果?

Node a;
Node b;

a的大小是0,b的大小是0,那么,a和b的地址是不是很可能重复了?

所以,为了保证不同的对象拥有不同的地址,最简单的方法就是保证所有类型的大小都不是0

所以,为了保证这点,大多数c++编译器都会给空结构或类加上一个冗余的字节保证类型不为空。

我的解释的清楚么?如果我的表达能力不够好,看这里,解释的足够详细。 当然,还有其他很多我没有想到的诡异的东西可以拿来sizeof,如果你想到了,欢迎跟我分享。至于c++中的sizeof类,基类,派生类,足够可以作为一个专门的文章了,先不再这里说,等我学会C++的再写一下相关内容(-_-")。

最后,给一个稍微给力点的程序,大家看看最终得到的结果是什么(注意这是一个c++程序):

//this is a cpp file
typedef   struct   weekday_st
{
        enum   week     {sun=123456789,mon,tue,wed,thu,fri,sat,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,
x,y,z,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak}; enum day{monring, moon, aftermoon}; }weekday_st;   int main(int argc, char *argv[]) { printf( "sizeof(weekday_st)=%d\n ", sizeof(weekday_st)); printf( "sizeof(weekday)=%d\n ", sizeof(weekday_st::week)); printf( "sizeof(day)=%d\n ", sizeof(weekday_st::day)); return 0; }

参考书目:《C专家编程》 《C语言深度解剖:解开程序员面试笔试的秘密 》

建议继续学习:

  1. Swift 的sizeof 和 sizeofValue    (阅读:855)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1