如何实现以下目标?取消引用并为指针赋值,并在一行中将指针递增(uint64_t)个字节。
// 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 :(得分:1)
[我怎么能]取消引用并为指针赋值并在一行中将指针递增(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;
总的来说,尽管C允许从一个对象指针类型转换为另一个对象指针类型,但它很少有关于如何安全地使用转换结果的承诺。此外,这样的强制转换违反了严格的别名规则,这可能有助于优化编译器生成错误且难以调试的程序。
答案 1 :(得分:0)
因此增量运算符的主题需要是可修改的左值。
当你施放它时,你的表达不再是左值。
现在,您可以使用类似的方法增加取消引用的结果
*(*x)++
...例如,这符合......
int f(int **x)
{
return *(*x)++;
}
答案 2 :(得分:0)
你可以写*(*(uint64_t**) &myvalue)++ = 34;
,但为什么你会这样做?
上面的行有效,因为转换产生一个rvalue,即只能在赋值的右侧(此处的赋值是++
),并且取消引用会产生一个左值(可以在左侧)。 / p>
另外,正如其他人所说,解除引用指针是未定义的行为。
答案 3 :(得分:-2)
将unsigned int*
投射到uint64_t*
然后取消引用uint64_t*
本身就是错误的。
暂时不理会这个事实......
由于运营商优先权,
*((uint64_t*) myvalue)++ = 34;
相当于:
*(((uint64_t*) myvalue)++) = 34;
即。它会在解除引用之前先递增指针。
当你使用演员表时,你得到一个右值。你不能增加或减少右值。
此外,还不清楚为什么要首先增加从强制转换中获取的临时指针。除非你有一个你想要在之后使用的变量,否则增加或减少指针是没有意义的。