2012-04-07 122 views
7

我正在瀏覽我的教科書,我對那裏的一些代碼有些困惑。在一個部分,他們以下面的方式進行指針運算:void *與char *指針算術

void* bp; 
... 
bp = (void*)((char*)(bp)+16); 
... 

但後來,他們做到以下幾點:

void* bp; 
... 
bp = bp+16; 
... 

我覺得他們應該是兩個不同的東西,但他們治療它就像是一樣的東西。 我有這樣的感覺,因爲,例如,如果你是做一個陣列連接(整型數組爲例),你會做以下

int* a = malloc(n*sizeof(int)); 
... 
q = *(a+1); 
... 
在這種情況下

,不是我訪問下一整數數組中有4個字節,而不是下一個字節? 同樣,我覺得如果我有void * a,那麼*(a + 1)應該是接下來的4個字節... 或者是不是這種情況? 謝謝。

+0

第二個例子不應該編譯。 – 2012-04-07 20:48:32

+1

@OliCharlesworth:如果在合規模式下編譯,它將不會編譯(或至少會觸發警告)。默認情況下,gcc不符合要求,並將'void *'算術作爲擴展。 – 2012-04-07 20:54:00

回答

11

這是一個滑倒。關於void *的算術不是由標準定義的,但是一些編譯器將其作爲擴展提供,其行爲與算術的char *相同。第二個是正式無效的C,但大概出於(壞)習慣。

+0

因此,訪問接下來的16個字節的正確方法是先將其轉換爲char *,然後再添加16個字節?大聲笑,現在要改變大量的代碼。哦,我抄下了第一個有點不對的地方,我做了一個小改動,但我認爲這對我的問題沒有任何影響。 – de1337ed 2012-04-07 20:50:11

+0

或者你可以投到'uint64_t *'並加2;)是的,可移植的方式是投射到一個指向已知大小的類型的指針並對其進行算術運算。如果您不需要可移植性,並且您的編譯器文檔使用'void *'算法以特定方式工作,那麼您可以使用它。但是,當然,在某些時候,你將不得不移植到不同的編譯器中...... – 2012-04-07 20:53:24