懂这个程序,就记住如何使用sizeof了

 
#include <stdio.h>

int main()
{
    union u1
    {
        double a;
        int b;
    }u1;
    union u2
    {
        char a[13];
        int b;
    }u2;

    union u3
    {
        char a[13];
        char b;
    }u3;

    union u4
    {
        char a[13];
        int b;
    }u4;

    union u5
    {
        char a[13];
        char b;
    }u5;

    struct s1
    {
        char a;
        double b;
        int c;
        char d;
    }s1;

    struct s2
    {
        char a;
        char b;
        int c;
        double d;
    }s2;

    struct s11
    {
        char a[8];
    }s11;

    struct s22
    {
        double d;
    }s22;

    struct s33
    {
        struct s11 s;
        char a;
    }s33;

    struct s44
    {
        struct s22 s;
        char a;
    }s44;


printf("size of u1 is %d.\n",sizeof(u1));//8
printf("size of u2 is %d.\n",sizeof(u2));//16
printf("size of u3 is %d.\n",sizeof(u3));//13
printf("size of u4 is %d.\n",sizeof(u4));//16
printf("size of u5 is %d.\n",sizeof(u5));//13
printf("size of s1 is %d.\n",sizeof(s1));//24
printf("size of s2 is %d.\n",sizeof(s2));//16
printf("size of s11 is %d.\n",sizeof(s11));//8
printf("size of s22 is %d.\n",sizeof(s22));//8
printf("size of s33 is %d.\n",sizeof(s33));//9
printf("size of s44 is %d.\n",sizeof(s44));//16

return 0;

}


结论:复合数据类型,如union,struct,class的对齐方式为成员中对齐方式最大的成员的对齐方式。

结论1:都知道union的大小取决于它所有的成员中,占用空间最大的一个成员的大小。所以对于u1来说,大小就是最大的double类型成员a了,所以 sizeof(u1)=sizeof(double)=8。但是对于u2和u3,最大的空间都是char[13]类型的数组,为什么u3的大小是13,而 u2是16呢?关键在于u2中的成员int b。由于int类型成员的存在,使u2的对齐方式变成4,也就是说,u2的大小必须在4的对界上,所以占用的空间变成了16(最接近13的对界)。

 

 

结论2 :struct 里面的元素是顺序存储的,每个元素占用的字节数根据对齐字节数N(struct 里占用字节最多的元素与CPU对齐字节数中较小的一个)进行调整.如果从左至右M个元素加起来的字节数大于N,则按从右至左舍去K个元素直至M-K个元素 加起来的字节数小于等于N,如果等于N则不用字节填充,小于N则把M-K-1的元素填充直至=N. 

 

附:设置对齐方式

一 #pragma pack ( [ show ] | [ push | pop ] [, identifier ] , n )


 

[]里面的是可有可无的但是n一定要指定,如果没有编译器默认n=8

使用方法:

1.	#pragma pack(push) //保存对齐状态  
2.	#pragma pack(1)//设定为1字节对齐  
3.	#pragma pack(show); //编译的时候会在警告信息里面体现具体的字长的设置信息  
4.	struct test  
5.	{  
6.	
7.	    char m1;  
8.	
9.	    double m4;  
10.	    int   m3;  
11.	};  
12.	#pragma pack(pop)


 

test将不再以double的大小为准则,开始用1个字节的对齐方式。

二 另外一种设置对齐方式的是:

__declspec( align( # ) )


 

里面#必须的是2的n次方,从1,2,4,8,16到8192,这样的话,如果定义一个结构体,他将以结构体的大小为准,补足到最临近的#的的整数倍。

比如:

__declspec(align(8)) struct Str1{ 

    int a, b, c, d, e; 

    char f; 

    char *g; 

}; //本身是25个字节补足到最近的8的倍数也就是32 

__declspec(align(4)) struct Str1{ 

    int a, b, c, d, e; 

    char f; 

    char *g; 

}; //本身是25个字节补足到最近的4的倍数也就是28


 

另外,需要注意。

另外有一点要注意的就是GCC编译的程序,最大就是以4字节对齐,,不管你怎么弄,或者说怎么设置,它是不可能以8比如double来对齐的,比如:

struct test 
{     
    char m1; 
    double m4; 
} 


 

gcc编译的话,那么他的大小是多少呢?如果不设置对齐的话是12,4个字节对齐的结果.

但是如果设置了:

#pragma pack(8)

是什么效果?

依旧是4个字节对齐,而且 #pragma pack()是属于c语言的,跟系统无关,不管是windows还是linux!

 

你可能感兴趣的:(linux,windows,struct,gcc,include,编译器)