2015-04-23 108 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; 

那麼你不應該得到任何印刷,因爲它強制在同一對準被分配爲是地址總線寬度的變量。爲什麼你想這樣做,我不知道,因爲編譯器知道如何做比這些程序員更好的事情。

相關問題