gcc 是否不允许对操作的左值进行类型转换?

s3fp2yjn  于 2023-08-06  发布在  其他
关注(0)|答案(7)|浏览(151)

我有下面的代码,我正在做一个类型转换的整数指针到空指针,并试图分配字符地址。

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;

ifsvaxew

ifsvaxew1#

ptr = (int *)&a ;

字符串
更自然但不便于携带可能给予人的印象是它在小端机器上工作(现在大多数),但依赖于&a之后的字节为空。但事实并非如此。
我建议

printf("%d\n", (int)a) ;

qni6mghb

qni6mghb2#

左值的强制转换是有效的,即(void *)ptr本身是有效的,但它不再是左值。这被称为左值转换
正如@Joachim评论的那样:

ptr = (int *) &a;

字符串

xpcnnkqh

xpcnnkqh3#

是的,在C中不能强制转换赋值运算符的左操作数。
另外,在你的例子中,你可以用另一种方式来让你的代码工作:

void main()
{
   int *ptr;
   char a = 10;
   ptr = (int*) &a; // this is perfectly fine
   printf("%d\n", *ptr);
}

字符串

baubqpgj

baubqpgj4#

变量或表达式的类型转换结果为r值。所以(void *)ptr给出了r-value,你试图将&a分配给r-value。它是类似0x 12345 =&a的东西,这是错误的,所以你需要得到l值。

oaxa6hgo

oaxa6hgo5#

这个问题与你的例子不符--但是你的问题的答案(而不是你的例子)是肯定的--你可以。以下是方法:

void encode_fixed32(char *buffer,float input) {
  ((float *)buffer)[0]=input;
}

void decode_fixed32(char *buffer) {
  return ((float *)buffer)[0];
}

字符串

wtzytmuj

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;
}

0g0grzrc

0g0grzrc7#

很抱歉晚了8年才讨论这个问题,但我遇到它是因为我有一个类似的问题,并在C中找到了解决方案。这个问题的出现是因为,正如其他人所说,像(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

相关问题