2016-11-11 38 views
-1

這裏是我的代碼從一個字節數組反序列化uint64_t中值:編譯器警告有關未定義操作

uint8_t* s = blah; 

uint64_t output = 
    (((uint64_t)*s++) << 56) + 
    (((uint64_t)*s++) << 48) + 
    (((uint64_t)*s++) << 40) + 
    (((uint64_t)*s++) << 32) + 
    (((uint64_t)*s++) << 24) + 
    (((uint64_t)*s++) << 16) + 
    (((uint64_t)*s++) << 8) + 
    (((uint64_t)*s)  ); 

我編譯此代碼使用g ++在Ubuntu版本5.4。

雖然代碼工作完全按照預期,我得到的最後一行編譯時警告:

warning: operation on 's' may be undefined [-Wsequence-point] 

想知道什麼可能是錯誤的,我怎麼能解決這個問題。問候。

+0

可能的重複https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points –

+0

各種's ++'子表達式的評估順序是未指定的。在這種情況下,同一個對象被多次修改,這個標準不僅僅是說它們可以以任何順序被評估(這足夠糟糕),並且說行爲是完全不確定的。 –

+2

任何你不使用簡單循環的理由?讓編譯器進行展開。 – Olaf

回答

3

您的代碼對變量s進行了非序列修改。這種行爲是未定義的。您可以使用索引,而不是前進的指針修復它(我假設你正在閱讀一個little-endian的變量這是不明顯的,從你的代碼。):

uint64_t output = 
    (((uint64_t)s[0]) << 56) + 
    (((uint64_t)s[1]) << 48) + 
    (((uint64_t)s[2]) << 40) + 
    (((uint64_t)s[3]) << 32) + 
    (((uint64_t)s[4]) << 24) + 
    (((uint64_t)s[5]) << 16) + 
    (((uint64_t)s[6]) << 8) + 
    (((uint64_t)s[7])  ); 
1

你的代碼修改的值s七次在指令內,然後第八次使用它。如果C標準或C++標準接收到可能導致此類代碼執行或使其執行不可避免的輸入,那麼C標準或C++標準都不會對其實施什麼要求。但是,請注意,如果程序從不接收會導致代碼執行不可避免的輸入,那麼在應用程序中存在此類代碼將不會影響應用程序的正確性,因此這不是編譯錯誤。使用s [0],s [1],s [2]等調整代碼將使代碼更加清晰並避免這些問題。

+0

1)這就是C++,2)C標準清楚地表明這是未定義的行爲。 3)C++相同。 – Olaf