我有下面的代码,我正在做一个类型转换的整数指针到空指针,并试图分配字符地址。
void main() { int *ptr; char a = 10; (void *)ptr = &a; printf("%d\n", *ptr); }
字符串我得到下面的错误,有没有办法,我可以解决这个问题?
error: lvalue required as left operand of assignment (void *)ptr = &a;
型
ifsvaxew1#
ptr = (int *)&a ;
字符串更自然但不便于携带可能给予人的印象是它在小端机器上工作(现在大多数),但依赖于&a之后的字节为空。但事实并非如此。我建议
&a
printf("%d\n", (int)a) ;
qni6mghb2#
左值的强制转换是有效的,即(void *)ptr本身是有效的,但它不再是左值。这被称为左值转换。正如@Joachim评论的那样:
(void *)ptr
ptr = (int *) &a;
字符串
xpcnnkqh3#
是的,在C中不能强制转换赋值运算符的左操作数。另外,在你的例子中,你可以用另一种方式来让你的代码工作:
void main() { int *ptr; char a = 10; ptr = (int*) &a; // this is perfectly fine printf("%d\n", *ptr); }
baubqpgj4#
变量或表达式的类型转换结果为r值。所以(void *)ptr给出了r-value,你试图将&a分配给r-value。它是类似0x 12345 =&a的东西,这是错误的,所以你需要得到l值。
oaxa6hgo5#
这个问题与你的例子不符--但是你的问题的答案(而不是你的例子)是肯定的--你可以。以下是方法:
void encode_fixed32(char *buffer,float input) { ((float *)buffer)[0]=input; } void decode_fixed32(char *buffer) { return ((float *)buffer)[0]; }
wtzytmuj6#
编辑:这个答案只适用于C++,而不是C,但可能是相关的。
你必须将左值转换为一个指向指针的引用,而不是一个指针,然后赋值就可以工作了:
void main() { int *ptr; char a = 10; (void *&)ptr = &a; printf("%d\n", *ptr); }
字符串注意void * 后面的&。这样你就可以保持它的左值性,并且可以赋值给它。然而,在这种特殊情况下,printf行为仍然是未定义的,因为你将char重新解释为int,即使你假设小端,你仍然可能在表示10**的字节之后有3个未定义的字节。更好的使用案例:
int a[5]; int *ptr = a + 2; // points to the element with index=2 (char *&)ptr += sizeof(int); // advances the pointer to the next element
型这是有用的,例如当你在CUDA或嵌入式设备上对数组执行strided for循环时,你想提前缓存确切的步骤,以避免每次在循环中乘以4:
const int stride = sizeof(int)*step; int *my_ptr = first_ptr; for (int i = 0; i < count; ++i) { ... (char *&)my_ptr += stride; }
0g0grzrc7#
很抱歉晚了8年才讨论这个问题,但我遇到它是因为我有一个类似的问题,并在C中找到了解决方案。这个问题的出现是因为,正如其他人所说,像(void *)ptr这样的强制转换不会产生左值,所以你不能赋值给它。但是像*(void **)&ptr * 这样的解引用指针是 * 一个左值。你可以将代码改为:
*(void **)&ptr
void main() { int *ptr; char a = 10; *(void **)&ptr = &a; printf("%d\n", *ptr); }
字符串这个编译和运行都很好,并且做了我认为你想让它做的事情。它给出奇数输出,因为值输出部分来自char a变量附近的未初始化字节,所以这样做是危险的,但它是有效的C。Modified code compiling and running here
char a
7条答案
按热度按时间ifsvaxew1#
字符串
更自然但不便于携带可能给予人的印象是它在小端机器上工作(现在大多数),但依赖于
&a
之后的字节为空。但事实并非如此。我建议
型
qni6mghb2#
左值的强制转换是有效的,即
(void *)ptr
本身是有效的,但它不再是左值。这被称为左值转换。正如@Joachim评论的那样:
字符串
xpcnnkqh3#
是的,在C中不能强制转换赋值运算符的左操作数。
另外,在你的例子中,你可以用另一种方式来让你的代码工作:
字符串
baubqpgj4#
变量或表达式的类型转换结果为r值。所以(void *)ptr给出了r-value,你试图将&a分配给r-value。它是类似0x 12345 =&a的东西,这是错误的,所以你需要得到l值。
oaxa6hgo5#
这个问题与你的例子不符--但是你的问题的答案(而不是你的例子)是肯定的--你可以。以下是方法:
字符串
wtzytmuj6#
编辑:这个答案只适用于C++,而不是C,但可能是相关的。
你必须将左值转换为一个指向指针的引用,而不是一个指针,然后赋值就可以工作了:
字符串
注意void * 后面的&。这样你就可以保持它的左值性,并且可以赋值给它。
然而,在这种特殊情况下,printf行为仍然是未定义的,因为你将char重新解释为int,即使你假设小端,你仍然可能在表示10**的字节之后有3个未定义的字节。
更好的使用案例:
型
这是有用的,例如当你在CUDA或嵌入式设备上对数组执行strided for循环时,你想提前缓存确切的步骤,以避免每次在循环中乘以4:
型
0g0grzrc7#
很抱歉晚了8年才讨论这个问题,但我遇到它是因为我有一个类似的问题,并在C中找到了解决方案。这个问题的出现是因为,正如其他人所说,像
(void *)ptr
这样的强制转换不会产生左值,所以你不能赋值给它。但是像*(void **)&ptr
* 这样的解引用指针是 * 一个左值。你可以将代码改为:字符串
这个编译和运行都很好,并且做了我认为你想让它做的事情。它给出奇数输出,因为值输出部分来自
char a
变量附近的未初始化字节,所以这样做是危险的,但它是有效的C。Modified code compiling and running here