简体   繁体   English

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

[英]Is typecasting on lvalue of operation not allowed?

I have the below code, where i am doing a type cast of integer pointer to void pointer and try to assign char address. 我有下面的代码,我正在做一个整数指针到void指针的类型转换,并尝试分配char地址。

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

I am getting below error, Is there anyway that i can fix this? 我收到以下错误,无论如何,我能解决这个问题吗?

error: lvalue required as left operand of assignment
    (void *)ptr = &a;

Yes, you cannot cast the left operand of the assignment operator in C. 是的, 您不能在C中转换赋值运算符的左操作数

Also, in your case you could just do it the other way to make your code work: 另外,在您的情况下,您可以通过另一种方式使代码工作:

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

The cast on lvalue is valid, ie, (void *)ptr itself is valid, but it's not an lvalue anymore. 左值上的强制转换有效,即(void *)ptr本身有效,但它不再是左值。 This is called lvalue conversion . 这称为左值转换

The fix, as @Joachim commented: 正如@Joachim评论的那样:

ptr = (int *) &a;
ptr = (int *)&a ;

is more natural but it's not portable. 更自然,但它不便携。 Might give the impression it works on little endian machine (most nowadays) but relies on byte after &a being null. 可能会给它在小端机器上工作的印象(现在大部分时间),但依赖于字节后面&a为空。 Which it's not the case. 事实并非如此。

I would suggest 我会建议

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

type cast of of a variable or expression results in r-value. 变量或表达式的类型转换导致r值。 so (void *)ptr gives r-value and you are trying to allocate &a to r-value. so(void *)ptr给出了r值,你试图将&a分配给r值。 it is something like 0x12345=&a which is wrong so you are getting l-value is required. 它是像0x12345 =&a这是错误的,所以你需要l值。

The question doesn't match your example - but the answer to your question (instead of your example) - is yes - you can. 这个问题不符合您的例子-但回答你的问题 (而不是你的例子) -是肯定的-你可以。 Here's how: 这是如何做:

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

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

EDIT : this answer only works in C++, not C, but might be relevant nevertheless. 编辑 :这个答案只适用于C ++,而不是C,但可能仍然相关。

You have to cast your lvalue to a reference-to-a-pointer instead of a pointer, and then the assignment will work: 你必须将你的左值转换为引用指针而不是指针,然后赋值将起作用:

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

Note the & after void * . 注意 after void * This way you preserve its lvalue-ness and you can assign into it. 这样你就可以保留它的左值,你可以分配它。

However, in this particular case the printf behaviour will still be undefined because you are reinterpreting a char as an int, and even if you assume little endian, you may still have 3 undefined bytes after the byte representing 10 . 但是,在这种特殊情况下,printf行为仍然是未定义的,因为您将char重新解释为int,即使您假设为小端,在字节表示10之后仍可能有3个未定义的字节。

A better use case: 一个更好的用例:

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

This is useful eg when you are doing a strided for-loop over an array in CUDA or on an embedded device, and you want to cache the exact step in advance to avoid multiplication by 4 every time inside the loop: 这很有用,例如当您在CUDA或嵌入式设备上对数组进行跨步循环时,您希望提前缓存准确的步骤以避免每次在循环内乘以4:

const int stride = sizeof(int)*step;
int *my_ptr = first_ptr;
for (int i = 0; i < count; ++i) {
    ...
    (char *&)my_ptr += stride;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM