sizeof(结构体)的值

来源:互联网 发布:新手淘宝买什么摄影棚 编辑:程序博客网 时间:2024/05/29 12:46

在笔试时,老是看到它定义一个结构体,要你给出这个结构体sizeof()的值。
首先,给出c语言常用类型的sizeof大小。

    printf("char: %d\n",sizeof(char));    printf("char*: %d\n",sizeof(char*));    printf("short: %d\n",sizeof(short));    printf("int: %d\n",sizeof(int));    printf("signed: %d\n",sizeof(signed));    printf("unsigned: %d\n",sizeof(unsigned));    printf("long: %d\n",sizeof(long));    printf("float: %d\n",sizeof(float));    printf("double: %d\n",sizeof(double));输出结果:    char: 1    char*: 8    short: 2    int: 4    signed: 4    unsigned: 4    long: 4    float: 4    double: 8

指针大小是8个字节,是因为我是在64位系统编译运行的。指针的作用是指向一个地址,它的大小跟地址线多少是一致的。(1字节8位,刚接触的时候我怎么也记不住。一般存储大小是指存储字节的多少,64K内存表示能放64K个字节)

那么笔试它考结构体的字节数是为了考什么?是考你对结构体数据的字节对齐和位域对齐的了解。大多数时候,只考到字节对齐。编译器为什么要进行字节对齐,因为某些机器对数据的存储有要求,对结构体中的数据只能从某些固定位置开始,否则会出错。再者,存储的规范有利于它高效的读取。具体为什么高效,计组磁盘那一张我学得不认真,有兴趣的同学可以再回去看一看。

结构体数据对齐的存储规则是这样的。先找结构体中位数最长的数据,决定了结构体存储时是按照最长数据的字节数为单位存储。举个例子

struct test2{    char a;    char b;    double c;    char d;};

求sizeof(test2)的值,它会先找出结构体中最长的基本数据,就是double c,它占8位,那么结构体分配内存时以8字节为单位,那么上面那个结构体的字节值是4*8=24吗?

不是的,这里还有第二个约定,就是前后连续出现一致的数据类型,在结构体给定的内存单位内可以连续放置,直到占完一个单位分配下一个单位,或是没有使用完以0补充剩余位数。char长度为1,前面说过,test2以8为单位分配内存,那么char a 和char b占据[0,1],剩下的[2…7]则补充0。

那如果结构体中有另外一个结构体作为成员呢,如

struct test3{    char e;    struct test2 a;};

它的内存长度是不是等价于

struct test4{    char e;    char a;    char b;    double c;    char d;};

并不等价。sizeof(test3)=32,sizeof(test4)=24,区别在于char和struct并不是一致类型,所以test3中的char e 只能单独占一个单位,即8字节。

灵活的c语言告诉你,它不仅可以决定结构体内存分配的单位,还可以决定每次分配最少占用的字节数。下面这个语句可以强行设置每次对变量分配的最少字节长度。你可以试试。

#pragma pack(n) /* n = 1, 2, 4, 8, 16 */

那么位域对齐又是怎么回事呢。我们常说,数据是以字节的形式占用内存的。但有时候,我们并不需要那么多个位。比如,这个数据出现的范围只可能是0…3,那么2位就足够存储它了,我们不需要用到c中整形的最小范围short,即16个位。

多事的c语言给出了如下一种定义方式,可以一个变量仅占用基本数据的几个位。还是那个规则,前后一致的数据可以放在同一个单位内存里。单位内存由最长成员数据长度决定。

struct test5{    char a:1;    char b:1;    char :2;    long c:3;    char d:2;};

在这里,a和b可以占用同一个单位内存(此时a和b占用的是单位内存第一个字节的前两位),所以结构体长度是12。记住,未命名的位域定义是无意义的,因为对结构体操作时无法取到未命名的位域,所以编译器会将它优化掉。即在上面这个结构体中(char :2;)这句是可有可无的,跟定义了一个空语句( ;)是一样的。

如果位域定义中夹杂着数据定义呢?

struct test6{    char a:1;    char b:1;    char :2;    long c:3;    char d:2;    double d;};

将位域定义看做普通的数据定义就好。具体是不是这样,啊,a和b分配时是不是位于同一字节,我的Dev-c一调试就出错,希望能有人实验后来告诉我。

1 0
原创粉丝点击