我有~16k行1998年的老式C代码(约50个主要编程),当时在gcc下完美构建但现在失败了许多"左值作为赋值的左操作数"第一个例程中的错误," stutter.c"。我没有足够的C程序员来找到问题,而且似乎无法在互联网上搜索特定于我的问题的答案(使用这个相当通用的错误消息)。
以下是具体细节:
从(vintage)Makefile编译行:
gcc -O3 -Wall -D__dest_os = unix -I / usr / X11 / include -DPLOTX11 -c -o stutter.o ../ src / stutter.c
失败的陈述示例:
cell_car(cell) = free_list;
cell_type(cell) = type;
cell_name(atom) = strdup(name);
cell_cdr(list) = binding_list;
cell_cdr(cell_car(current)) = b;
...(和很多类似的)
之前是:
typedef enum CELL_ENUM {
CELL_LAMBDA, CELL_SFUNC, CELL_VFUNC, CELL_LIST, CELL_ATOM
} CELL_TYPE;
typedef struct CELL_STRUCT {
void *car, *cdr;
unsigned type : 7;
unsigned mark : 1;
char empty[3];
} CELL;
和
#define cell_car(c) ((CELL *)(c)->car)
#define cell_cdr(c) ((CELL *)(c)->cdr)
#define cell_name(c) ((char *)(c)->car)
#define cell_func(c) ((CELL *(*)())(c)->car)
#define cell_type(c) ((CELL_TYPE)(c)->type)
#define cell_mark(c) ((c)->mark)
如果需要,可提供更多代码详情。这里有一些明显的弃用功能可以解释这个错误吗?
作为一名科学的Fortran程序员,我有多年的经验,但在学习足够的C语言以完全转换之前已退休。 Haven在http://gcc.gnu.org/bugs/找到了有关遗留代码的任何有用信息。我感谢任何能帮助我完成C,C ++和gcc教育的帮助,然后才能在linux下为我当前的项目工作。非常感谢!
答案 0 :(得分:11)
gcc不再允许您分配演员。
即
((CELL *)(cell)->car) = free_list;
不再合法。它不是投射lhs来匹配rhs,而是倾向于投射rhs以匹配lhs。解决这个问题的一种方法是获取左值的地址,将其作为指针强制转换,然后取消引用该指针,因此赋值为指针取消引用而不是转换。
即
*((CELL **)&(cell)->car) = free_list;
这可以通过更新宏来处理,所以它应该是非常轻松的......
即
#define cell_car(c) (*((CELL **)&(c)->car))
等...
然后可以将此宏用作左值或右值。
答案 1 :(得分:1)
除了更改代码以获取地址,转换指针和取消引用外,还可能需要使用“no_strict_aliasing”选项。 C99增加了一些规则,旨在促进优化,这使得系统状态的C模型成为一堆unsigned char[]
。其中最臭名昭着的是严格的别名规则。虽然将指针强制转换为“将此指针指向的东西解释为X”的代码可能会编译,但使用一种类型写入指针并使用另一种类型进行读取通常会产生未定义的行为,而某些编译器会将其解释为许可证表现为以时间和因果关系法无约束的相当奇怪和奇异的方式。