在C中转换增量和赋值

问题描述 投票:-7回答:4

我怎样才能实现以下目标?取消引用并为指针赋值,并在一行中将指针递增(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
c pointers casting
4个回答
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允许从一个对象指针类型转换为另一个对象指针类型,但它很少有关于如何安全地使用转换结果的承诺。此外,此类强制转换违反了严格的别名规则,这可能有助于优化编译器生成错误且难以调试的程序。


0
投票

你可以写*(*(uint64_t**) &myvalue)++ = 34;,但你为什么要那样做?


上面的行有效,因为转换产生一个rvalue,即只能在赋值的右边(这里的赋值是++),并且dereference产生一个左值(可以在左边)。

此外,正如其他人所指出的,解除引用您的铸造指针是未定义的行为。


0
投票

因此增量运算符的主题需要是可修改的左值。

当你施放它时,你的表达不再是左值。

现在,您可以使用类似*(*x)++的内容来增加取消引用的结果...例如,这符合......

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

-2
投票

unsigned int*投射到uint64_t*然后解除引用uint64_t*本身是错误的。

暂时不理会这个事实......

由于运营商的优先权,

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

相当于:

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

即,在解除引用之前,它首先递增指针。

当你使用演员表时,你得到一个右值。您不能递增或递减右值。

此外,还不清楚为什么要首先增加从强制转换中获取的临时指针。除非你有一个你想要在之后使用的变量,否则增加或减少指针是没有意义的。

© www.soinside.com 2019 - 2024. All rights reserved.