C 语言结构体长度的对齐(CentOS 6.3 64位)

网上搜索了一些文章来看,难懂,难理解,而且与我的测试并不相符合

我用下面的js生成c代码

var strstruct = '';
var strcall = '';
var strx = '';
var csize = 0;
var ts = '';

for(i=0;i<64;i++){
	//第2、3、4测试用到
	if(i%3==1){
		strx += "	uint i"+i+";\n";
		csize+=4;
		ts+='i';
	}
	//第4测试用到
	else if(i%3==2){
		strx += "	ulong i"+i+";\n";
		csize+=8;
		ts+='l';
	}
	//第1、3、4测试用到
	else{
		strx += "	ushort i"+i+";\n";
		csize+=2;
		ts+='s';
	}
	strstruct += "\
typedef struct{\n\
"+strx+"\n\
}s"+i+";\n";
	
	strcall += '	printf("sizeof(s'+i+')=%d/%d'+ts+'\\n", sizeof(s'+i+'), '+csize+');\n';
}

var str = '#include <stdio.h>\n\
#include <stdlib.h>\n\
#include <dlfcn.h>\n\
#include <string.h>\n\
'+strstruct+'\n\
void main(){\n\
	'+strcall+'\n\
}\n';


console.log(str);

 

进行了4次测试,结果如下:

1、分别打印了有1到64个ushort的struct的长度,发现长度规律为: 成员数 * 2

2、分别打印了有1到64个uint的struct的长度,发现长度规律为: 成员数 * 4

3、生成64个struct,每个struct成员规律为 int short int short,即第n(0开始)个成员的类型 = n%2==0?int:short,发现长度规律为: 成员数 * 4

4、生成64个struct,每个struct成员规律为 short int short int,即第n(0开始)个成员的类型 = n%2==1?int:short,发现长度规律为: 除第一个长度为2委外,其它都是 成员数 * 4

5、生成64个struct,每个struct成员规律为 short int long short int long,即第n(0开始)个成员的类型 = n%3=0?short:(n%3==1?int:long),长度规 members后字符代表成员顺序和类型(s=short, l=long, i = int):

sizeof(s0)=2/2 members:s
sizeof(s1)=8/6 members:si
sizeof(s2)=16/14 members:sil
sizeof(s3)=24/16 members:sils
sizeof(s4)=24/20 members:silsi
sizeof(s5)=32/28 members:silsil
sizeof(s6)=40/30 members:silsils
sizeof(s7)=40/34 members:silsilsi
sizeof(s8)=48/42 members:silsilsil
sizeof(s9)=56/44 members:silsilsils
sizeof(s10)=56/48 members:silsilsilsi
sizeof(s11)=64/56 members:silsilsilsil
sizeof(s12)=72/58 members:silsilsilsils
sizeof(s13)=72/62 members:silsilsilsilsi
sizeof(s14)=80/70 members:silsilsilsilsil
sizeof(s15)=88/72 members:silsilsilsilsils
sizeof(s16)=88/76 members:silsilsilsilsilsi
sizeof(s17)=96/84 members:silsilsilsilsilsil
sizeof(s18)=104/86 members:silsilsilsilsilsils
sizeof(s19)=104/90 members:silsilsilsilsilsilsi
sizeof(s20)=112/98 members:silsilsilsilsilsilsil
sizeof(s21)=120/100 members:silsilsilsilsilsilsils
sizeof(s22)=120/104 members:silsilsilsilsilsilsilsi
sizeof(s23)=128/112 members:silsilsilsilsilsilsilsil
sizeof(s24)=136/114 members:silsilsilsilsilsilsilsils
sizeof(s25)=136/118 members:silsilsilsilsilsilsilsilsi
sizeof(s26)=144/126 members:silsilsilsilsilsilsilsilsil
sizeof(s27)=152/128 members:silsilsilsilsilsilsilsilsils
。。。。。。。。。

规律是长度增加时增加8字节,也就是长度为8的n次方且这个长度能够存下所有成员!

 

总结结构体长度跟成员的规律:

1、长度增加值根据最长的成员决定:最长的是多长,增加长度时就增加多少。

2、长度大于等于成员本身的长度和

 

也就是:

1、成员类型相同时,长度为:成员个数*单个成员长度

2、成员类型长度不一样时,假设成员最短为n,最长为m,结构体实际长度l:

    a、l % n == 0,l是n的倍数

    b、最多浪费的空间为m-n。(这句话只在上面的第4个测试成立)

    c、浪费的空间可以使用:        

typedef struct {
        ushort size;
        char key;
        ulong nKeyLength;
} StringBucket;

这个的长度是16,key的相对位置是2。3、4、5、6、7个位置是“浪费”的,

但你实际这样是不会出错的:

StringBucket sb;  
memcpy((char*)sb +sizeof(ushort), "abcdef", 6);

上面代码并不会越界。

    d、成员顺序不同,结构长度不同

typedef struct {
        uint size;
        char key;
        ulong nKeyLength;
} StringBucket;

长度16;

typedef struct {
        uint size;
        ulong nKeyLength;
        char key;
} StringBucket;

长度24;

把长的成员放前面,占空间更小。具体我总结不出规律,用下面的代码,来检查成员的位置:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>

typedef struct {
        uint size;
        ulong nKeyLength;
        char key;
} StringBucket;

void printBitOfByte(char $x){
        int $y;
        for($y=7;$y>-1;$y--){
                printf("%d",($x>>$y)&0x01);
        }
        printf(" ");
}


void printStr(char *str, int len){
        char c;
        int i=0;
        while(1){
                c = str[i++];
                if(--len<0)
                        break;

                printBitOfByte(c);
                if(i%8==0)
                                        printf("\n");
                else
                                        printf(" ");

        }
        printf("\n");
}

void main(){
        StringBucket sb;
        memset(&sb, 0, sizeof(StringBucket));
        sb.size=1;
        sb.nKeyLength=3;
        sb.key=7;
        printf("size=%d\n", sizeof(StringBucket));
        printStr((char*)&sb, sizeof(StringBucket));
}

size=24
00000001  00000000  00000000  00000000  00000000  00000000  00000000  00000000 
00000011  00000000  00000000  00000000  00000000  00000000  00000000  00000000 
00000111  00000000  00000000  00000000  00000000  00000000  00000000  00000000 

可以看出size和key后面都有浪费。

用我上面的代码来优化你的内存占用吧

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值