在C中转换增量和赋值

时间:2016-06-28 17:24:05

标签: c pointers casting

如何实现以下目标?取消引用并为指针赋值,并在一行中将指针递增(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

4 个答案:

答案 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;

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

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

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