聊聊 GCC 中的 int 类型和字节对齐

默认分类 2024-04-17 1034 次浏览 次点赞


聊聊 GCC 中的对齐

GCC

最近看到一个问题,在 64 位操作系统中。实际测试环境 Ubuntu 22.04,GCC 11。

struct test{
    long a
    int b;
    char c
}

sizeof(stuct test) =?当然我知道这道题想考察的 int/long 定义以及对齐问题,之前编码也不会太在意这类似问题,直接打印出来就行,但是作为考题这里有诸多不严谨地方。我们好好探索下。

不管三七二十一,直接编译打印。

$ gcc test.c 
$ ./a.out 
16

显然地,这里 int 为4个字节,char 被4字节对齐。

看几个 GCC 选项

-m64

https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gcc/x86-Options.html#x86-Options

-m32
-m64
-mx32
-m16
-miamcu
Generate code for a 16-bit, 32-bit or 64-bit environment. The -m32 option sets int, long, and pointer types to 32 bits, and generates code that runs on any i386 system.

The -m64 option sets int to 32 bits and long and pointer types to 64 bits, and generates code for the x86-64 architecture. For Darwin only the -m64 option also turns off the -fno-pic and -mdynamic-no-pic options.

The -mx32 option sets int, long, and pointer types to 32 bits, and generates code for the x86-64 architecture.

The -m16 option is the same as -m32, except for that it outputs the .code16gcc assembly directive at the beginning of the assembly output so that the binary can run in 16-bit mode.

The -miamcu option generates code which conforms to Intel MCU psABI. It requires the -m32 option to be turned on.

看起来这里默认最大设置都是4字节对齐。

$ gcc test.c -m16 #编译失败
$ gcc test.c -m32
$ ./a.out 
12
$ gcc test.c -m64
$ ./a.out 
16

-fpack-struct

https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gcc/Code-Gen-Options.html#Code-Gen-Options

-fpack-struct[=n]
Without a value specified, pack all structure members together without holes. When a value is specified (which must be a small power of two), pack structure members according to this value, representing the maximum alignment (that is, objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location.

显然地,这里的编译选项能够设置 long 类型和对齐。先看默认值。

$ gcc test.c -fpack-struct=1
$ ./a.out 
13
$ gcc test.c -fpack-struct=2
$ ./a.out 
14
$ gcc test.c -fpack-struct=4
$ ./a.out 
16
$ gcc test.c -fpack-struct=8
$ ./a.out 
16

_attrribute_

这里能够设置 -m32 将 long 和指针类型设置为 4字节,但是对齐方式还是 4字节。

  • https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html

    struct test_a {
            char a; //1
            int b;  //4
            long c; //8
    }
    __attribute__ ((packed)) ;                 //13
    //__attribute__ ((aligned(1))) ;           //16
    //__attribute__ ((aligned(2))) ;           //16
    //__attribute__ ((aligned(4))) ;           //16
    //__attribute__ ((aligned(8))) ;           //16
    //__attribute__ ((aligned(16))) ;          //16

    packed 为字节对齐,aligned 不管设置多少都是4自己对齐。

结论

如下结论。

选项描述
-m32<br/>-m64<br/>-mx32<br/>-m16<br/>-miamcu设置 long 和指针数据类型长度,-m32为4个字节,-m64 为8个字节。
-fpack-struct设置对齐,支持 1、2、4字节对齐。
_attrribute_设置对齐,支持 1、4字节对齐。

本文由 Jay 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处,点赞0

还不快抢沙发

添加新评论