void foo(void *ptr, int numBytes)
{
(char*)ptr += numBytes;
}
这不能在c中编译。我知道另一种选择。但为什么这不起作用呢?有什么问题吗?
问题
问题是(char*)ptr
不会产生左值,这意味着该值不能修改-可以将其视为强制转换的临时结果,强制转换将产生类型为char*
的右值。
在语义上和下面的例子是一样的,强制转换产生一个临时值,这样的值不能被赋给一个新值。
int x = 123;
(float)x += 0.12f; /* (1), illegal */
/* ^-- sementically equivalent to `123.f += 0.12f` */
<
解决方案/strong>
在你的问题中,你已经说过你已经知道这个问题的解决方法,但我想明确地写解决方案,以显示如何修改ptr
的值,即使强制转换产生不可修改的值。
- 取指针的地址给void,
- 将此地址转换为指向char的指针的指针,
- 对该指针解引用,生成一个指向char的指针,
- 修改此yield lvalue,就像原来的
void*
是char*
类型一样
<一口> 一口>
*((char**)&ptr) += numbytes; // make `ptr` move forward `numbytes`
(注意:当对指针解引用时,得到一个左值,否则无法改变指向位于指针存储地址的值的值。)
这是因为
(char*)ptr
不是左值
试试这个:
void foo(void *ptr, int numBytes)
{
char* p = (char*)ptr;
p += numBytes;
}
更新strong>
各种值类型的简要说明可以在cppreference.com上找到。本文讨论的是c++中的值类型,但其核心思想可以转换为C。
为了讨论的目的,
左值是标识非临时对象或非成员函数的表达式。
可以将左值的地址赋值给另一个值。
的例子:
int i;
int* p = &i;
i = 20;
相比之下,
右值("pure"右值)是标识临时对象(或其子对象)或不与任何对象关联的值的表达式。
字面值42
是右值。你不能这样做:
int* p = &42;
42 = 53;
本行
char* p = (char*)ptr;
一个左值(p
)是从(char*)ptr
创建的。因此,可以使用:
p += numBytes;
在=
的左侧,您需要lvalue
。但是(char*)ptr
不是左值