2017-03-17 55 views
1

在下面的虛擬實例中,我得到一個警告,我不明白我怎麼能擺脫它沒有明確定義一個指針與int *_str = (int*)str錯誤類型參數遞增

#include <stdlib.h> 
#include <stdint.h> 

void foo(void *str, int c, size_t n) { 
    for (size_t i = 0; i < n; i++) 
     *((int*)str++) = c; 
} 

這裏是我的得到gcc

gcc -c -std=c99 -Wpointer-arith test.c 
test.c: In function ‘mymemset’: 
test.c:7:20: warning: wrong type argument to increment [-Wpointer-arith] 
     *((int*)str++) = c; 
        ^

我的代碼有什麼問題?

注意

我知道這個問題是非常相似,這one,但它並不能解釋爲什麼我不能這樣做,爲什麼我得到一個錯誤。

+2

'++((int *)str ++)= c;' - >'*((int *)(str)+ i)= c;' – LPs

+4

+++操作符的優先級高於cast 'int *'。但是*爲什麼*你想把這麼多東西塞進這麼幾個字?您是否參加了混淆的代碼競賽? –

+0

@AndrewHenle我很好奇,我認爲使用第三個變量會給出更加混淆的代碼。 – nowox

回答

1

str是指向void的指針。由於void是好的,無效的,並且沒有大小,可憐的編譯器怎麼可能明白你的意思是str++

str++應該使str指向下一個對象,但由於類型void不能是任何對象的類型str++是沒有意義的。

雖然你投到了int *,++比cast更具有「綁定」(這裏「優先」這個詞在這裏混淆了)。

+0

從技術上講,這是違反約束的 –

0

由於您誤解了*((int*)str++) = c應該做的事情,您感到X-Y問題。所以你的問題不是關於void算術,而是一個lvalue後增量。

讓我們將void問題分開一段時間,並考慮int64_tint32_t,它們的32位體系結構字節可尋址的大小爲8和4。總之,兩種類型的大小不同。

如果你想投int32_t*int64_t*,分配給它的價值和後增量的指針,你可能已經寫過如下(從你的例子inspirated):

int32_t* p = &value; 
*((int64_t*)p++) = 42; 

據經營者precedence命令執行是:

  1. 採取p
  2. 保存它後增爲int32_t *
  3. 鑄造它的int64_t *
  4. 取消對它的引用,並指定42爲
  5. 的int64_t
  6. 後增量p

這個例子構建完美的,但它不是做你認爲它。需要什麼是後期增量轉換指針。所以,你還需要一個括號:

*(((int64_t*)p)++) = 42; 

這一次,因爲((int64_t*)p)被視爲lvalue,因此它不能被修改,你會得到一個錯誤。

在這種特殊情況下,你絕對需要第三個變量來完成這個技巧。

這與您的void指針完全相同。