如何为gcc指定默认的全局变量对齐?

时间:2017-12-16 11:23:25

标签: c gcc alignment

默认情况下,如何使用GCC删除所有全局变量的对齐(下面为.align 4),而不必为每个变量指定__attribute__((aligned(1)))

我知道我所要求的是普遍适用的一个坏主意,因为在某些架构中,1的对齐不会起作用,因为例如CPU无法取消引用未对齐的指针。在我的情况下,我正在编写一个i386引导加载程序,并且未对齐的指针在那里很好(但速度较慢)。

源代码(a.c):

__attribute__((aligned(1))) int answer0 = 41;
int answer = 42;

编译:{{1​​}}

装配输出(gcc -m32 -Os -S a.c):

a.s

标志 .file "a.c" .globl answer .data .align 4 .type answer, @object .size answer, 4 answer: .long 42 .globl answer0 .type answer0, @object .size answer0, 4 answer0: .long 41 .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4" .section .note.GNU-stack,"",@progbits 将所有struct成员和结构的对齐方式更改为1.例如,使用该标志

gcc -fpack-struct=1

编译为变量struct x { char a; int b; }; struct y { int v : sizeof(char) + sizeof(int) == sizeof(struct x); }; struct z { int b; }; struct x x = { 1, 1 }; int i = 42; struct z z = { 2 }; z'没有对齐,但变量x' and(类型.align 4)仍然有i。我需要一个解决方案,它也使int不对齐,而不必为每个这样的变量指定额外的东西。

2 个答案:

答案 0 :(得分:1)

使用打包结构来保存空间的IMO打包变量是最简单,最安全的方法。

示例:

#include <stdio.h>
#include <stdint.h>

#define _packed __attribute__((packed))


_packed struct 
{
    uint8_t x1; 
    _packed int x2;
    _packed uint8_t x3[2];
    _packed int x4;

}byte_int;

int main(void) {
    printf("%p %p %p %p\n", &byte_int.x1, &byte_int.x2, &byte_int.x3, &byte_int.x4);
    printf("%u %u %u %u\n", (unsigned int)&byte_int.x1, (unsigned int)&byte_int.x2, (unsigned int)&byte_int.x3, (unsigned int)&byte_int.x4);    // I know it is an UB just to show the op in dec - easier to spot the odd and the even addresses

    return 0;
}

https://jsfiddle.net/dsb87pxz/

答案 1 :(得分:0)

很可能gcc没有这样的标志,可以改变全局变量的默认排列。

gcc -fpack-struct=1可以是一种解决方法,但仅适用于恰好是struct类型的全局变量。

同时对gcc的.s输出进行后期处理并删除(部分).align行可以作为解决方法。