2016-06-28 66 views
-7

如何實現以下目標?取消引用並將值分配給指針,並通過一行中的(uint64_t)字節來增加指針。鑄造增量並在C中分配

// random address 0xDEADBEEF 
unsigned int *myvalue = 0xDEADBEEF; 
*((uint64_t*) myvalue)++ = 34; 

錯誤產生是由於鑄造如果我刪除了鑄造那麼它「作品」,但不是我想要的結果。

unsigned int *myvalue = 0xDEADBEEF; 
*(myvalue)++ = 34; 

我希望通過的聲明是什麼:

// myvalue points to 0xDEADBEEF 
*((uint64_t*) myvalue)++ = 34; 
//myvalue points to 0xDEADBEEF + (64/8) 
// at 0xDEADBEEF (a random address) should contain 34 
+0

不,我想首先解開它,分配值,然後增加 – Har

+2

請告訴我們你得到什麼和你的期望。並告訴我們你實際上想要達到的目標。 –

+0

你是否先嚐試增量然後施放。 – denis

回答

1

[我怎麼能DE-參考和值賦給一個指針,並增加由(uint64_t中)的教鞭於一身行的字節[?]

您正在試圖做太多的事情用一個單一的表達。你應該分手。而且,「一條線」或多或少是任意的。我可以把你的一行內容分散在12條非空行上,我可以採用多行並將它們結合在一起。最接近真正有意義的事情將是一個完整的表達。

不過,如果你堅持在一個完整的表達做了,你願意承擔的int的大小均勻地把一個uint64_t的大小,那麼你可能會做它像這樣:

unsigned int *myvalue = 0xDEADBEEF; 
*myvalue = 34, myvalue += (sizeof(uint64_t)/sizeof(int)); 

當然,這大多是圍繞「完整表達」的含義的詭辯 - 使用分號而不是逗號運算符會更好,但會有兩個完整表達式。但這是你選擇搭帳篷的理由。

另外,如果你打開改變myvalue類型,那麼這將是一個有點清潔劑來做這樣的:

uint64_t *myvalue = 0xDEADBEEF; 
* (int *) (myvalue++) = 34; 

但總體而言,雖然Ç許可證從一個對象指針鑄造鍵入另一個,它幾乎沒有承諾如何轉換的結果可以安全地使用。此外,這種強制轉換違反了嚴格的別名規則,這可能會導致優化編譯器產生不正確且難以調試的程序。

+0

您如何在下面給出的例子被認爲是打破了別名規則?由於有一個uint64_t,它稍後會轉換爲int。 – Har

-2

unsigned int*uint64_t*,然後提領該uint64_t*是錯誤的本身。

忽視這個事實了一會兒......

由於運算符優先級,

*((uint64_t*) myvalue)++ = 34; 

等同於:

*(((uint64_t*) myvalue)++) = 34; 

即它解引用之前先遞增指針。

當你使用一個強制轉換時,你會得到一個右值。你不能增加或減少右值。

另外,目前還不清楚爲什麼要首先增加從演員獲得的臨時指針。除非你有一個以後想要使用的變量,否則增加或減少指針是毫無意義的。

+1

取消引用給你一個左值。 – 2501

+0

@ 2501肯定,這就是爲什麼我們確定他是否意味着取消引用*然後*增量或反之亦然 – oldrinb

+0

是的,我想先解除引用,分配然後遞增。 – Har

0

因此,增量運算符的主題需要是可修改的左值的

當你施放它時,你的表情不再是一個左值。

現在,你可以增加的東西提領的結果一樣 *(*x)++ ...例如,這是符合...

int f(int **x) 
{ 
    return *(*x)++; 
} 
+0

所以你基本上是說因演員陣容而無法在一行中做到這一點? – Har

+0

所以如上所述,一個解除引用不會賦予一個左值後的左值? – Har

+1

它的確如此,但是,解除表達的並不是你正在增加的東西。 – DigitalRoss

0

可以*(*(uint64_t**) &myvalue)++ = 34;,但爲什麼會你做吧?


上述行工作,因爲鑄造產生一個右值,即只能在賦值語句的右邊(這裏的任務是++),並取消引用產生一個左值(可在左側)。

另外,正如其他人所指出的,解引用您的鑄造指針是未定義的行爲。

+0

反饋歡迎。 – a3f