我有以下代码:
struct something {
char *(*choices)[2];
};
char* arr[2] = {"foo", "bar"};
int main(void) {
struct something obj;
obj.choices = &arr;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我使用普通的C编译器(gcc)进行编译时,没有任何错误。但是,我正在为Z80进行编译,它会引发一个ERROR (152) Operands are not assignment compatible,其描述为:
试图分配一个不能将其类型提升为目标类型的值。
我不明白&arr和的类型char *(*choices)[2]会有何不同。我该怎么做才能解决此问题?
(我正在使用Zilog z80编译器,它是ZDS 5.2.0的一部分)
Zilog 支持声称这实际上不是编译器错误,并且原始代码无法编译,因为它不是严格的 ANSI C。它被 GCC 接受,因为编译器是“宽松的”并且添加了更多语法规则超出 ANSI C 规范。以下是完整回复:
\n\n\n\n\nGCC 编译器虽然非常好,但不一定是 C 标准的完美实现。多年来,我见过一些广泛使用的编译器(例如 MSVC++,以及不太常见的 GCC)接受非严格 ANSI C 语法的情况,而该语法似乎是标准 C 的无害准扩展并且 \xe2\x80\x99s 不存在被解释为某种替代的合法含义的危险。这可能是另一个例子。
\n\n这里涉及到 C 语法的一个要点,这是我对此点的理解,以及为什么 GCC 允许客户使用原始语法。一旦函数指针(例如正确定义的变量 fnPtr)获得了定义,就可以通过表达式调用它,而无需前面的 * 间接运算符,例如
\n\n\n\n
result = fnPtr(x); // This is legal syntax\xe2\x80\xa6\n\n
result = (*fnPtr) (x); // \xe2\x80\xa6 even though this is \xe2\x80\x9cmore correct\xe2\x80\x9d允许使用上面显示的第一种语法的原因是,包含参数 x 的括号被视为 C 运算符,其类型为 \xe2\x80\x9c 指向函数\xe2\x80\x9d 的指针。因此,当函数指针实际用于进行函数调用时,这些括号的存在使得间接运算符变得不必要。但是,在像此客户代码这样的情况下,您只是在赋值语句中使用函数指针,这不会发挥作用,因此实际上这些操作数并不严格分配兼容。然而,如果不是专家语言管理员的用户期望如果函数指针可以在一个地方不带 * 的情况下使用,那么它在其他上下文中也应该是可以接受的,这很难被指责。这可能就是 GCC 开发人员显然决定接受 user\xe2\x80\x99s\n 语法的原因。
\n
这是编译的替代版本:
\n\nstruct something {\n char *(*choices[2]);\n};\n\nchar* arr[2] = {"foo", "bar"};\n\nint main(void) {\n struct something obj;\n *obj.choices = &arr;\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n