2016-06-28 65 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