编译c代码:错误:需要左值作为赋值的左操作数
当我尝试在 gcc 4.4.5 上编译一些代码时,gcc 在这一行遇到错误:
ORG(e) = DEST(a);
这两个宏定义为:
#define ORG(e) ((site_struct *) ODATA(e))
#define DEST(e) ((site_struct *) DDATA(e))
我在使用 gcc 3.4.5 在 solaris 上编译此代码时没有遇到问题。
我一直试图找出为什么它不能编译很长一段时间但无济于事。有人能指出我正确的方向吗?
来自评论:
ODATA 和 DDATA 定义为:
#define ODATA(e) ((edge_struct *)((e)&0xfffffffcu))->data[(e)&3]
#define DDATA(e) ((edge_struct *)((e)&0xfffffffcu))->data[((e)+2)&3]
When I try to compile some code on gcc 4.4.5, gcc runs into an error on this line:
ORG(e) = DEST(a);
These 2 macros are defined as:
#define ORG(e) ((site_struct *) ODATA(e))
#define DEST(e) ((site_struct *) DDATA(e))
I did not have a problem compiling this on solaris with gcc 3.4.5.
I've been trying to figure out why it won't compile for quite a while but to no avail. Can anyone point me in the right direction?
From a comment:
ODATA and DDATA are defined as:
#define ODATA(e) ((edge_struct *)((e)&0xfffffffcu))->data[(e)&3]
#define DDATA(e) ((edge_struct *)((e)&0xfffffffcu))->data[((e)+2)&3]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我很难相信你可以在 Solaris 上编译它。作业的左侧是强制转换的结果。 C 语言中的强制转换结果始终是右值。您不能将任何内容分配给右值。这么简单没有任何意义。右值不是对象。它们不存储在内存中,这就是为什么尝试将任何内容分配给右值是没有意义的。这是 C 的一个非常基本的事实,这就是为什么我不敢相信你可以用任何 C 编译器来编译它。
例如,此代码
无法编译的原因与您的代码无法编译的原因完全相同。
很难“为你指明正确的方向”,因为完全不清楚你想要做什么。该任务的含义是什么?为什么要在作业的两侧进行强制转换?
I find it hard to believe you could compile it on Solaris. The left-hand side of your assignment is a result of a cast. The results of casts in C language are always rvalues. You can't assign anything to an rvalue. It simple makes no sense. Rvalues are not objects. They are not stored in memory, which is why trying to assign anything to an rvalue makes no sense. This is a very fundamental fact of C, which is why I can't believe you could compile it with any C compiler.
For example, this code
does not compile for the very same reason your code does not compile.
It is hard to "point you in the right direction" because it is totally not clear what you were trying to do. What is that assignment supposed to mean? Why do you want to have casts on both sides of the assignment?
您的
ODATA()
和DDATA()
宏计算为左值(这些宏中的转换是指向取消引用以获得左值的指针)。因此,需要弄清楚原始ORG()
和DEST()
宏的作用:基本上,它们采用
ODATA()
生成的左值> 和DDATA()
宏并将它们视为指针。 GCC 3.4.5 的强制转换为左值语言扩展在 3.4.5 中已弃用并在 4.0 中删除,如果强制转换的操作数是左值,则允许将强制转换的结果用作左值。我们可以通过执行我们自己的指针/地址操作和取消引用来模拟这一点。更改ORG()
和DEST()
宏以获取由ODATA()
和DDATA( 生成的左值的地址)
宏,然后取消引用该地址作为指向所需类型的指针。这应该在 GCC 4.x 中产生与您使用现有宏在 GCC 3.4.5 中获得的相同结果:我认为这应该产生与 GCC 3.4.5 中原始代码相同的行为 - 大概这是正确的行为应用。
一些注意事项:
我将对
ODATA()
和DDATA()
宏进行较小的修改,将它们括在括号中。我不确定是否有必要,因为->
和[]
运算符具有非常高的优先级,但我对未完全加括号的表达式宏感到偏执:Your
ODATA()
andDDATA()
macros evaluate to lvalues (the cast in those macros is to a pointer that's dereferenced to obtain the lvalue). So what needs figuring out is what the originalORG()
andDEST()
macros do:Basically they take the lvalues produced by the
ODATA()
andDDATA()
macros and treat them as pointers. GCC 3.4.5's cast-as-lvalue language extension, which was deprecated in 3.4.5 and removed in 4.0, allows the result of a cast to be used as an lvalue if the operand to the cast is an lvalue. We can emulate that by performing our own pointer/address manipulation and dereferencing. Change theORG()
andDEST()
macros to take the address of the lvalues produced by theODATA()
andDDATA()
macros, then dereference that address as a pointer to the desired type. This should produce equivalent results in GCC 4.x as you were getting in GCC 3.4.5 with your existing macros:I think that should produce the same behavior that the original code had in GCC 3.4.5 - presumably that's the correct behavior for this application.
A couple of notes:
I'd make a minor modification to the
ODATA()
andDDATA()
macros by enclosing them in parens. I'm not sure it necessary since the->
and[]
operators have a very high precedence, but I get paranoid about expression macros that aren't fully parenthesized:强制转换的结果是右值,而不是左值。 IOW,结果只是“原始”值,而不是作为值来源的原始对象。
如何解决您的情况并不完全清楚。特别是,在不知道 ODATA(e) 和 DDATA(e) 是什么/做什么的情况下,很难猜测如何从那里继续。
如果您尝试将一个结构分配给另一个结构,您可以执行以下操作:
请注意,即使我们在分配的两侧都有强制转换,我们也不会尝试分配给强制转换的结果 - 相反,我们将指针转换为正确的类型,然后取消引用该指针,并分配给该指针引用的对象。
编辑:好的,在扩展宏之后,我们最终会得到这样的结果:
基于其纯粹的丑陋,我想我会尝试备份至少几个抽象级别并尝试找出其意图所有这一切。这非常接近只写编码。尽管您已按要求提供了 ODATA 和 DDATA 的定义,但看起来弄清楚这一点需要的不仅仅是这些 - 您需要仔细查看
edge_struct
的定义,并且可能<代码>site_struct也是如此。您几乎必须弄清楚edge_struct
的data
成员中的下标的含义。长话短说,这看起来像是一个相当严重的逆向工程案例,几乎不可能预测需要检查和理解多少代码才能重写/更新它,直到您获得现代编译器的正确结果。
The result of a cast is an rvalue, not an lvalue. IOW, the result is just the "raw" value, not the original object that was the source of the value.
It's not entirely apparent how to fix things in your case. In particular, without knowing what the ODATA(e) and DDATA(e) are/do, it's hard to guess how to proceed from there.
If you're trying to assign one struct to another, you can do something like:
Note that even though we have casts on both sides of the assignment, we're not trying to assign to the result of the cast -- rather, we're casting a pointer to the correct type, and then dereferencing that pointer, and assigning to the object that pointer refers to.
Edit: okay, after the macros are expanded, we end up with something like this:
Based on the sheer ugliness of that, I think I'd try to back up at least a couple levels of abstraction and try to figure out the intent of all this. This is pretty close to write-only coding. Although you've provided the definitions of ODATA and DDATA as requested, it looks like figuring this out will take more than that -- you'll need to look closely at the definition of
edge_struct
, and possiblysite_struct
as well. You'll almost have to figure out the meaning of the subscripts into thedata
member of theedge_struct
.To make a long story short, this looks like a fairly serious case of reverse engineering, and it's almost impossible to predict how much code will need to be examined and understood before you can rewrite/update it to the point that you'll get the right result from a modern compiler.