2015-04-23 34 views
-2

我正在开发嵌入式系统项目。我的目标是32位(32位地址总线)。如何知道编译器是否执行内存对齐?

我需要知道编译器是否执行内存对齐。

换句话说,如果我声明了以下变量:

uint16_t x = 0xFFFF; 

x将被保存在一个特定条目类似:

Address 0x00000000 -> FFFF0000 

或者可以将它保存这样的:

Address 0x00000000 -> 000000FF 

Address 0x00000001 -> FF000000 
+0

1.它会给你什么? 2.试着去看看你是否有这种感觉,如果你是全部定下来的话。 – Eregrith

+0

阅读编译器的手册。通常,编译器提供了在静态分配的变量上指定显式对齐控制的方法,如'#pragma DATA_ALIGN'。 – user3528438

+0

此外,如果您正在进行微控制器编程,您通常会拥有一个“映射文件”的好处,它可以完全显示如何分配所有内容以及在什么地址。 – Lundin

回答

1

当然,你的编译器总是会做出明智的选择e目标架构。

通常,它会将数据类型与该数据类型的“自然”地址对齐。这不会错误地对齐变量,以便访问它会导致一些错误或具有灾难性的性能。

对于你的特殊情况,如果x是一个局部变量,它可能会在一个寄存器或堆栈中,而不是一个事先已知的绝对地址。大多数平台都有堆栈对齐的规则可能会发挥作用(即当进入某个函数时,堆栈可能始终与某些2的幂对齐)。如果它不是本地自动的,则上述内容将适用,即编译器将以自然和“良好”的方式对齐变量。

+0

如果x是一个静态或全局的? –

+0

如果x是静态的或全局的(全局无论如何都是静态的)取决于你声明它的方式和位置! –

+0

无论是在'.data' /''.bss'还是在堆栈中分配,编译器仍然需要做相同的基本对齐考虑。这个答案的意思是,除此之外还有其他一些考虑因素,具体取决于堆栈的处理方式([有关堆栈处理的更多信息](http://en.wikipedia.org/wiki/Call_stack))。 – Lundin

0

可能是一个简单的方法来检查:

uint8_t *pChar; 
uint16_t x = 0xFF; 
(uint8_t *)pChar = (uint8_t *)&x; 

,然后打印:

*pChar*(pChar + 1)

这也有利于检查Endian的模式下,CPU英寸

0

如果您使用GCC编译器(可能作为交叉编译器定位您的系统),您可以使用__alignof__ keyword(它是GCC扩展)。您可能还需要使用packed variable attribute

由于Lundin明智评论,最新C11标准给你_Alignof关键字和_Alignas符。

因此,值得使用最近的编译器。

+1

或者只是使用C11编译器(例如GCC 4.9.x),然后使用标准的'_Alignof'关键字。 – Lundin

1

我只相信编译器完成其工作...否则我想你可以做一些“hackish的”东西发现:

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

int main() 
{ 
    uint16_t x = 0xFFFF; 
    uintptr_t align = (uintptr_t)&x % sizeof(uint16_t); 

    if(align != 0) // aint gonna happen 
    { 
    printf("Scandal! Variable incorrectly aligned!\n"); 
    } 

    align = (uintptr_t)&x % sizeof(uintptr_t); 
    if(align != 0) // might very well happen, not an issue 
    { 
    printf("Variable not aligned at an address which is a multiple of the CPU alignment\n"); 
    printf("At address %p, \"optimal\" %p", &x, (uint8_t*)&x - (uint8_t*)align); 
    } 


    return 0; 
} 

如果使用的是C11,你可以强制编译器使用不同的对齐方式。如果上面的代码更改为

_Alignas(uintptr_t) uint16_t x = 0xFFFF; 

那么你不应该得到任何印刷,因为它强制在同一对准被分配为是地址总线宽度的变量。为什么你想这样做,我不知道,因为编译器知道如何做比这些程序员更好的事情。

相关问题