您好我目前正在處理一個程序,我需要處理一個包含一系列可能未對齊(有時也是)未對齊的浮動的數據blob。 我正在爲gcc 4.6.2編譯ARM cortex-a8。 我不得不生成的彙編代碼的一個問題:GCC爲ARM上的未對齊浮動訪問生成彙編
作爲例子我寫了一個最小的例子:下面的測試代碼
float aligned[2];
float *unaligned = (float*)(((char*)aligned)+2);
int main(int argc, char **argv)
{
float f = unaligned[0];
return (int)f;
}
的編譯器(gcc 4.6.2 - 與優化-O3)產生
00008634 <main>:
8634: e30038ec movw r3, #2284 ; 0x8ec
8638: e3403001 movt r3, #1
863c: e5933000 ldr r3, [r3]
8640: edd37a00 vldr s15, [r3]
8644: eefd7ae7 vcvt.s32.f32 s15, s15
8648: ee170a90 vmov r0, s15
864c: e12fff1e bx lr
此處的編譯器無法知道數據是否對齊,但從來沒有使用過的VLDR需要對齊的數據,否則程序將因總線錯誤而崩潰。
現在這裏是我的實際問題:這是從編譯器是否正確,我需要照顧我的C++代碼對齊還是這是編譯器中的錯誤?
我也可以添加我當前的解決方法,它可以在訪問該值之前使gcc進行復制。訣竅是定義一個只包含一個帶有gcc packed屬性的float的結構,並通過一個結構指針訪問數據。代碼片段:
struct FloatWrapper { float f; } __attribute__((packed));
const FloatWrapper *x = reinterpret_cast<const FloatWrapper *>(rawX.data());
const FloatWrapper *y = reinterpret_cast<const FloatWrapper *>(rawY.data());
for (size_t i = 0; i < vertexCount; ++i) {
vertices[i].x = x[i].f;
vertices[i].y = y[i].f;
}
C99標準包含這個腳註:「在由一元運算符取消引用指針的無效值中,有一個是空指針,一個地址與所指向的對象的類型不恰當對齊......」。我毫不懷疑C++標準包含一個類似的警告。所以你的程序在技術上是未定義的,編譯器可以自由地產生任何它喜歡的指令序列,而不會成爲一個錯誤。 –