格物致知 c语言字节数、对齐、补齐的小探索

写在前面

工作几年了,由于信奉陶渊明的

“好读书,不求甚解”

(其实是懒)
的思想,很多概念其实了解的很模糊,最近工作中遇到一个问题:“64位环境下,指针占多少个字节?”,信誓旦旦的回答了4个字节,说指针无论32位环境下还是64位环境下,均占4个字节。
结果,可以想象,测试结果悲剧了。。。
这里格物致知一下,写了几个小demo,清晰一下混淆了很久的概念。

注:这里仅提供32和64位环境的测试结果,其实还有16位等,环境不好找,暂时放弃。

基本数据类型字节数

32位环境下字节数

charboolshort intintlong intlong long intfloatdoubleptrstruct ptr
1124484844

64位环境下字节数

charboolshort intintlong intlong long intfloatdoubleptrstruct ptr
1124884888

上面的表格,已经描述了大部分的差异,这里进一步解释一下特殊情况:

  1. 上面的short int/long int/long long int中的int可以省略。
  2. c标准中,并没有强制规定short < int < long,而是short <= int <= long,因此并不是说int就一定是4个字节,实际上,某些资料上说,16位环境下sizeof(int) = sizeof(short) = 2。
  3. 对于指针来说,32位平台下,4字节,64位平台下,8字节。

有关心测试用例和测试结果的朋友可以看看下面。

#include <stdio.h>                                                                                                                                                                                     
                                                                                                                                                                                                       
typedef struct tag_st                                                                                                                                                                                  
{                                                                                                                                                                                                      
    char b;                                                                                                                                                                                            
    short w;                                                                                                                                                                                           
    int dw;                                                                                                                                                                                            
} st;                                                                                                                                                                                                  
                                                                                                                                                                                                       
int main(int argc, char* argv[])                                                                                                                                                                       
{                                                                                                                                                                                                      
    printf("char size = %d\n", sizeof(char));                                                                                                                                                          
    printf("short size = %d\n", sizeof(short));                                                                                                                                                        
    printf("int size = %d\n", sizeof(int));                                                                                                                                                            
    printf("long size = %d\n", sizeof(long));                                                                                                                                                          
    printf("long int size = %d\n", sizeof(long int));                                                                                                                                                  
    printf("long long int size = %d\n", sizeof(long long int));                                                                                                                                        
    printf("float size = %d\n", sizeof(float));                                                                                                                                                        
    printf("double size = %d\n", sizeof(double));                                                                                                                                                      
    printf("ptr size  = %d\n", sizeof(char*));                                                                                                                                                         
    printf("struct ptr size = %d\n", sizeof(st*));                                                                                                                                                     
                                                                                                                                                                                                       
    return 0;                                                                                                                                                                                          
}                                                                                                                                                                                                      

32位平台结果

bennett@linux-hycc:~/WorkSpace/test> gcc test.c -o test -m32
bennett@linux-hycc:~/WorkSpace/test> ./test
char size = 1
bool size = 1
short int size = 2
int size = 4
long int size = 4
long long int size = 8
float size = 4
double size = 8
ptr size  = 4
struct ptr size = 4

64位平台结果

bennett@linux-hycc:~/WorkSpace/test> gcc test.c -o test -m64
bennett@linux-hycc:~/WorkSpace/test> ./test
char size = 1
bool size = 1
short int size = 2
int size = 4
long int size = 8
long long int size = 8
float size = 4
double size = 8
ptr size  = 8
struct ptr size = 8

结构体的对齐和补齐

默认情况

数据类型默认对齐字节
基本类型sizeof(基本类型)
数组sizeof(单个成员)
联合sizeof(最大成员)
结构体sizeof(每个成员)

对齐:

默认情况下,基本数据类型按照自身大小整数倍进行对齐,即每个成员的首地址应该是自身大小的整数倍。

  1. 特殊的,对于数组成员,按照每个成员的大小进行对齐;
  2. 对于联合,按照最大成员大小进行对齐;
  3. 对于结构体内包含结构体的,递归的按照结构体的对齐方式对齐。
数据类型默认补齐字节
基本类型min(max(sizeof(基本类型)), 4)

补齐:
默认情况下,按照最大成成员大小进行补齐,对于超过4字节的,按照4字节补齐。

#include <stdio.h>                                                                                                                                                                                     
                                                                                                                                                                                                       
typedef union tag_un                                                                                                                                                                                   
{                                                                                                                                                                                                      
    double  ld1;                                                                                                                                                                                       
    double  ld2;                                                                                                                                                                                       
    double  ld3;                                                                                                                                                                                       
    double  ld4;                                                                                                                                                                                       
} un;                                                                                                                                                                                                  
                                                                                                                                                                                                       
typedef struct tag_unn                                                                                                                                                                                 
{                                                                                                                                                                                                      
    short   w;                                                                                                                                                                                         
    char    b;                                                                                                                                                                                         
} unn;                                                                                                                                                                                                 
                                                                                                                                                                                                       
typedef struct tag_stt                                                                                                                                                                                 
{                                                                                                                                                                                                      
    double  ld1;                                                                                                                                                                                       
    double  ld2;                                                                                                                                                                                       
    double  ld3;                                                                                                                                                                                       
} stt;                                                                                                                                                                                                 
                                                                                                                                                                                                       
typedef struct tag_sttt                                                                                                                                                                                
{                                                                                                                                                                                                      
    char    arr1[11];                                                                                                                                                                                  
    short   arr2[1];                                                                                                                                                                                   
} sttt;                                                                                                                                                                                                
                                                                                                                                                                                                       
typedef struct tag_st                                                                                                                                                                                  
{                                                                                                                                                                                                      
    double  ld;                                                                                                                                                                                        
    char    arr1[2];                                                                                                                                                                                   
    char    *ptr;                                                                                                                                                                                      
    char    b;                                                                                                                                                                                         
    short   arr2[18];                                                                                                                                                                                  
    un      un;                                                                                                                                                                                        
    unn     unn;                                                                                                                                                                                       
    stt     stt;                                                                                                                                                                                       
} st;                                                                                                                                                                                                  
int main(int argc, char* argv[])                                                                                                                                                                       
{                                                                                                                                                                                                      
    st st = {0.0, "ab", NULL};                                                                                                                                                                         
                                                                                                                                                                                                       
    printf("struct st size = %d\n", sizeof(st));                                                                                                                                                       
                                                                                                                                                                                                       
    printf("struct sttt size = %d\n", sizeof(sttt));                                                                                                                                                   
                                                                                                                                                                                                       
    printf("ld address = %p\n", &st.ld);
    printf("arr1 address = %p\n", &st.arr1);
    printf("ptr address =  %p\n", &st.ptr);
    printf("b address =  %p\n", &st.b);
    printf("arr2 address = %p\n", &st.arr2);
    printf("un address = %p\n", &st.un);
    printf("unn address = %p\n", &st.unn);
    printf("stt address = %p\n", &st.stt);

    return 0;
}

执行结果如下:

32位平台:

bennett@linux-hycc:~/WorkSpace/test> gcc test.c -o test -m32
bennett@linux-hycc:~/WorkSpace/test> ./test
struct st size = 92
struct sttt size = 14
ld address = 0xff962210
arr1 address = 0xff962218
ptr address =  0xff96221c
b address =  0xff962220
arr2 address = 0xff962222
un address = 0xff962248
unn address = 0xff962250
stt address = 0xff962254

64位平台:

bennett@linux-hycc:~/WorkSpace/test> gcc test.c -o test -m64
bennett@linux-hycc:~/WorkSpace/test> ./test
struct st size = 104
struct sttt size = 14
ld address = 0x7ffc512757c0
arr1 address = 0x7ffc512757c8
ptr address =  0x7ffc512757d0
b address =  0x7ffc512757d8
arr2 address = 0x7ffc512757da
un address = 0x7ffc51275800
unn address = 0x7ffc51275808
stt address = 0x7ffc51275810

编译器命令

#pragma pack(n)

对齐:

数据类型默认对齐字节
基本类型min(sizeof(基本类型), n)
数组min(sizeof(单个成员), n)
联合min(sizeof(最大成员), n)
结构体min(sizeof(每个成员), n)

补齐:

数据类型默认补齐字节
基本类型min(max(sizeof(基本类型)), n)

写在结尾

想着好好写来的,结果用例的名字还是乱七八糟,暂时不改了,有机会再调整吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值