当我尝试在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]
答案 0 :(得分:5)
我发现很难相信你可以在Solaris上编译它。作业的左侧是演员表的结果。 C语言中的强制转换结果总是 rvalues 。您不能将任何内容分配给右值。这很简单没有意义。 Rvalues不是对象。它们不存储在内存中,这就是为什么尝试将任何内容分配给rvalue是没有意义的。这是C的一个非常基本的事实,这就是为什么我不相信你可以用任何C编译器编译它。
例如,此代码
int i;
(int) i = 5; /* ERROR */
由于代码无法编译的原因相同,无法编译。
很难“指出你正确的方向”,因为你完全不清楚你想要做什么。该任务应该是什么意思?你为什么要在任务的两边进行演员表?
答案 1 :(得分:1)
您的ODATA()
和DDATA()
宏评估为左值(这些宏中的强制转换是指向取消引用以获取左值的指针)。因此,需要弄清楚原始ORG()
和DEST()
宏的作用是什么:
#define ORG(e) ((site_struct *) ODATA(e))
#define DEST(e) ((site_struct *) DDATA(e))
基本上它们采用ODATA()
和DDATA()
宏生成的左值并将它们视为指针。 GCC 3.4.5的cast-as-lvalue语言扩展,在3.4.5中已弃用并在4.0中删除,如果转换的操作数是左值,则允许将转换的结果用作左值。我们可以通过执行我们自己的指针/地址操作和解除引用来模拟它。更改ORG()
和DEST()
宏以获取ODATA()
和DDATA()
宏生成的左值的地址,然后将该地址取消引用作为指向所需类型的指针。这应该在GCC 4.x中产生与您使用现有宏的GCC 3.4.5相同的结果:
#define ORG(e) (*((site_struct **) &(ODATA(e))))
#define DEST(e) (*((site_struct **) &(DDATA(e))))
我认为这应该产生与原始代码在GCC 3.4.5中相同的行为 - 可能这是该应用程序的正确行为。
几点说明:
我对ODATA()
和DDATA()
宏做了一些小修改,将它们包含在parens中。我不确定是否有必要,因为->
和[]
运算符具有非常高的优先级,但我对于没有完全括号的表达式宏感到偏执:
#define ODATA(e) (((edge_struct *)((e)&0xfffffffcu))->data[(e)&3])
#define DDATA(e) (((edge_struct *)((e)&0xfffffffcu))->data[((e)+2)&3])
答案 2 :(得分:0)
施法的结果是右值,而不是左值。 IOW,结果只是“原始”值,而不是作为值源的原始对象。
在你的案例中如何解决问题并不完全明显。特别是,在不知道ODATA(e)和DDATA(e)是什么/做什么的情况下,很难猜测如何从那里开始。
如果您尝试将一个结构分配给另一个结构,则可以执行以下操作:
*(site_struct *)a = *(site_struct *)b;
请注意,即使我们在赋值的两边都有强制类型转换,我们也不会尝试分配强制转换的结果 - 相反,我们正在转换指向正确类型的指针,然后取消引用该指针,并指定指针引用的对象。
编辑:好的,在扩展宏之后,我们最终得到类似的结果:
((site_struct *)((edge_struct *)((e)&0xfffffffcu))->data[(e)&3]) =
((site_struct *)((edge_struct *)((a)&0xfffffffcu))->data[((a)+2)&3]);
基于其纯粹的丑陋,我想我会尝试至少支持几个抽象层次,并试图找出所有这些的意图。这非常接近只写编码。虽然您已按要求提供了ODATA和DDATA的定义,但看起来这样做会花费更多 - 您需要仔细查看edge_struct
的定义,并可能{{1}也是。您几乎必须弄清楚site_struct
data
成员edge_struct
成员的含义。
总而言之,这看起来像是一个相当严重的逆向工程案例,而且几乎不可能预测需要检查和理解多少代码才能重写/更新它到你的位置。将从现代编译器中获得正确的结果。