2013-07-09 44 views
1

我正在管理每個uint8_t 4個標誌的數組。使用32位讀取原子讀取4個字節的數組

uint8_t flags[4]. 

這些標誌可以隨時由不同的線程改變。

我希望能夠通過使用一個原子操作獲得這些標誌的快照。 可以說,我做到以下幾點:

uint32_t temp_val = read_atomic32((uint32_t *) &flags[0]) 

現在我投回到標誌的數組:

uint8_t *my_flags = &temp_val; 
printf("flag zero is %d\n, my_flags[0]); 

我在這裏懷疑幾個問題:

  1. 也許標誌[4 ]未針對uint32_t讀取進行對齊,並可能導致不對齊的崩潰 或者可能由於非對齊訪問而導致原子功能不能保留。

  2. endians?應該發生問題嗎?即使我使用uint32_t我後來將其重新轉換爲uint8_t數組,並且我不認爲內存佈局會因此操作而發生更改 - 仍然可能我在此處缺少某些內容。 我在這裏假設,如果我讀了一個4字節的內存位置,這些模式將是相同的,直到無論你的機器是小端還是大端。

  3. 有沒有更好的方法來管理uint8_t的4個獨立標誌,但仍然能夠以便攜式安全方式使用一個動作來讀取它們整體?

回答

2

將您的旗幟工會:

union { 
    uint8_t c[4]; 
    uint32_t t; 
} flags; 

flags.c[0] = ...; 
flags.t = 0xffffffffU; 

這需要對準問題的關心,你可以使用類型雙關通過t訪問標誌不進行強制轉換。根據嚴格的ISO C規則,它不是很清楚,但通常會按照您的要求做。

當您分配文字值(如我的示例中)或在訪問flags.t時期望某些值時,Endianness成爲問題。只要讀一個值,然後寫一個剛讀的(未修改 - 沒有一點扭曲!)應該沒問題。

+0

謝謝。因此使用聯合會強制編譯器將此結構放置在對齊的地址上,因爲代碼可以訪問t。 –

+0

沒錯。聯合的對齊要求是其所有成員的最大對齊要求。由於所有成員都必須位於零點偏移處,因此可以保證「c」與「t」對齊。 – Jens

+0

出於實際原因,在大多數編譯器中使用聯合打字。但是我相信通過這個標準,編譯器可以將flags.c和flags.t存儲在不同的寄存器中,這會導致斷開的值。 –