为什么我不能对void指针的强制转换进行算术运算?

时间:2014-06-02 19:42:50

标签: c

void foo(void *ptr, int numBytes)
{
    (char*)ptr += numBytes;
}

这不用C语言编译。我知道替代方案。但为什么这不起作用?有什么问题?

3 个答案:

答案 0 :(得分:4)

问题

问题是(char*)ptr不会产生左值,这意味着该值无法修改 - 人们可以将其视为演员的临时结果,演员表将产生一个类型为char* rvalue

它在语义上与您拥有以下示例一样,转换产生临时值,这样的值不能分配新值。

int x = 123;

(float)x += 0.12f; /* (1), illegal                                     */
                   /*  ^-- sementically equivalent to `123.f += 0.12f` */

<强>解决方案

在你的问题中,你已经声明你已经知道这个问题的解决方法,但是我想明确地写一个解决方案来展示如何修改ptr的值,即使转换为非 - 可修改的价值观。

  1. 指针的地址设为void
  2. 将此地址强制转换为指向char ,
  3. 指针的指针
  4. 取消引用该指针,产生指向char 的指针,
  5. 修改此产量左值,就像原始void*类型为char*
  6. 一样

    *((char**)&ptr) += numbytes; // make `ptr` move forward `numbytes`
    

    注意:取消引用指针时会得到左值,否则无法更改指向值的值位于存储在指针中的地址。)

答案 1 :(得分:3)

=的左侧,您需要lvalue。但(char*)ptr不是左值。

答案 2 :(得分:3)

那是因为

(char*)ptr不是左值。

请改为尝试:

void foo(void *ptr, int numBytes)
{
    char* p = (char*)ptr;
    p += numBytes;
}

<强>更新

可以在cppreference.com找到各种价值类型的简要说明。这里讨论的是C ++中的值类型,但核心思想转化为C语言。

为了讨论的目的,

  

左值是一个表达式,用于标识非临时对象或非成员函数。

您可以获取左值的地址并指定其他值。

示例:

int i;
int* p = &i;
i = 20;

相比之下,

  

prvalue(“纯”rvalue)是一个标识临时对象(或其子对象)的表达式,或者是与任何对象无关的值。

文字42是一个右值。你做不到:

int* p = &42;
42 = 53;

在这一行中,

    char* p = (char*)ptr;

p创建左值((char*)ptr)。因此,可以使用:

    p += numBytes;