2015-08-31 74 views
0

數據對齊的問題在另一篇文章中,我問了一個編碼問題,並在源代碼中對這個問題,我宣佈以下列方式一些變量:從堆棧中分配 - 在C

char datablock[200]; 
char *pointer1=datablock; 
char *pointer2=datablock+100; 

然而有人指出,代碼可能與64位系統不兼容,因爲100不能被8整除?我不記得那是什麼。

但我想要做的是保留一大塊內存用於我的程序,並使其儘可能快地執行,我記得因爲系統緩存內存的工作方式,使用來自同一塊內存比使用獨立塊的數據更快。使用malloc也會要求更慢的內存。

所以在代碼中,這是我想要做的一個例子。我要分配40000個字節,並給4個指針訪問每個10,000字節:

char data[40000]; 
char *string0=data; 
char *string1=data+10000; 
char *string2=data+20000; 
char *string3=data+30000; 

然而,這不是我想要做的,因爲我相信不同的存儲部分將被訪問:

char string0[10000]; 
char string1[10000]; 
char string2[10000]; 
char string3[10000]; 

我相信我的想法是正確的,但我唯一需要關注的是對於64位系統,偏移值是8的倍數,對於32位系統,偏移值是4的倍數?

我不想挑選錯誤的數字並收到分段錯誤。

+3

*「但是有人提到代碼可能與64位系統不兼容,因爲100不能被8整除?」*有人錯了。 – Ryan

+0

如果您將該內存用於「char」以外的項目,則只會出現問題。例如,如果將「int」或「double」項放入該內存中,可能會出現問題。 – user3386109

+1

XY問題?你真的想要達到什麼?正如@ user3386109所述,除非您嘗試錯誤地將這些數組用作數據類型,否則應該沒有問題。如果你要緩存垃圾,你需要更具體,並提供更多的細節。 – Olaf

回答

2

可能出現的對齊問題與存儲具有指定對齊的對齊規則之外的對象有關。

這不是你的情況。您沒有將指針存儲在未對齊的地址中,您只是將地址存儲在對齊的指針中。

只是要清楚:

char *pointer2=datablock+100; 

此聲明可能根據這將如何被編譯但對於指針空間的分配本身是考慮到放在堆棧或寄存器指針編譯器,它將爲底層體系結構正確執行。

,當你做這樣的事情可能出現的問題:

int* asInteger = (int*) (datablock+1); 
*datablock = 10; 

在這種情況下,你試圖存儲它有一個地址對齊要求(int),這可能是不對齊到要求的值int

在任何情況下,如果我沒有記錯,x86架構允許它工作,但速度較慢。

+0

我想要可視化第二個代碼片段......這是否意味着你在一個64位系統中分配一個8字節指針,它存儲int大小字節的值,以便爲整數保留偏移量1到1 + int大小?而數字10覆蓋保留的整數空間的第一個字節,從而搞亂整數? – Mike

+0

在第二個代碼片段中,指向int的指針被分配(在堆棧上),而不是它指向的內存塊。由asInteger指向的塊將在數據塊後面開始1個字節,並且具有int大小(也許是4個字節)。第二行'* datablock = 10;'實際上不會混淆asInteger指向的int! –

+0

@Mike:在第二個代碼片段中,您告訴編譯器「獲取數據塊的地址,加1,並將結果地址視爲存儲'int'的地址。現在,一個特定的體系結構可能要求這個地址必須對齊到一個特定的大小,但是因爲你迫使它被認爲是'int *',所以這個條件可能不是真的。 – Jack

0

無論系統是32位還是64位,都不會導致您提到的代碼出現分段錯誤。在指針運算的這個例子:

char *pointer2=datablock+100; 

你說:從地址所指向的數據塊提前一個字符的尺寸爲100倍。您前進的號碼不一定是其他號碼的倍數。

關於最後的代碼片段,很可能內存的4個部分將在堆棧中連續,但是。

您可以通過打印指針地址來驗證並查看發生了什麼。例如。

printf("string0 %p\n", string0); 
printf("string1 %p\n", string1); 
printf("string2 %p\n", string2); 
printf("string3 %p\n", string3);