2016-12-15 79 views
1

代碼:我可以投這樣的指針嗎?

unsigned char array_add[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 

... 

if ((*((uint32_t*)array_add)!=0)||(*((uint32_t*)array_add+1)!=0)) 
{ 
... 
} 

我要檢查,如果數組是全零。所以自然我想到了將一個數組的地址(它也恰好是第一個成員的地址)轉換爲unsigned int 32類型,所以我只需要這樣做兩次,因爲它是一個64位,8個字節陣列。問題是,它已成功編譯,但程序每次都在這裏崩潰。

我在一個8位微控制器cortex-M0上運行我的程序。

我怎麼了?

+1

停止寫這樣的代碼!這看起來像是在呼喚麻煩;考慮到強制轉換未定義的行爲。你爲什麼不使用'uint32_t [2]? – Olaf

+1

而Cortex-M0不是8位的CPU! – Olaf

+0

爲什麼不使用指針? unsigned char * pt = array_add; ((*(pt)!= 0)||(*(pt + 1)!= 0)) – dante

回答

-3

我不知道,但如果你的數組有8個字節然後就分配基址到long long變量,並把它比作0,如果數組是全0

編輯1這應該解決您的檢查問題:奧拉夫的評論後,我會說,用int64_t替換long long。但是,爲什麼你不是一個迭代數組和檢查的簡單循環。 8個字符是你需要比較的。

編輯2:另一種方法可能是對數組的所有元素進行或運算,然後與0進行比較。如果全部爲0,則OR將爲零。我不知道CMP是快速還是OR。有關確切的CPU週期要求,請參閱Cortex-M0文檔,但是,我預計CMP會變慢。

+0

'long long'不保證擁有64位!唯一的事情OP是正確的是使用固定寬度類型。 – Olaf

+0

頁碼。 n1570.pdf中有28條說,long long的最小範圍需要64位。請告訴我一個地方,它說「long long」不能保證是64位。我錯過了規範中的其他東西嗎? – user902384

+2

你已經引用了相關部分!再次仔細閱讀! – Olaf

2

理論上這可以工作,但在實踐中有一件事你沒有考慮:對齊內存訪問。

如果uint32_t需要對齊的存儲訪問(例如,4個字節),則鑄造的unsigned char具有1隻字節對齊要求到uint32_t*一個陣列產生一個指針的uint32_t不對齊陣列。

根據documentation

沒有爲Cortex-M0處理器上未對齊訪問不支持。任何嘗試執行未對齊的內存訪問操作都會導致HardFault異常。

實際上,這只是危險和脆弱的代碼,在某些情況下調用未定義的行爲,正如Olaf指出的,並且更好地解釋here

+1

該代碼也違反了有效的類型規則,因此調用UB(其中的對齊是**一個**問題,其他包括編譯器優化)。 – Olaf

1

要測試多個字節,因爲代碼可以使用memcmp()

這是多快取決於編譯器作爲優化編譯器可能簡單地發出代碼,一次(或2 4個字節)比較快速8字節的代碼。即使是memcmp()在8位處理器上可能也不會太慢。分析代碼有助於。

注意微優化,因爲它們往往不能有效地使用編碼器的時間來進行顯着的優化。

unsigned char array_add[8] = ... 
const unsigned char array_zero[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
if (memcmp(array_zero, array_add, 8) == 0) ... 

另一種方法使用一個union。小心不要假設add.arr8[0]是最重要還是最不重要的字節。

union { 
    uint8_t array8[8]; 
    uint64_t array64; 
} add; 

// below code will check all 8 of the add.array8[] is they are zero. 
if (add.array64 == 0) 

一般來說,注重字跡清晰的代碼和儲備這麼小的優化,以非常選擇的情況下。