奇怪的编译器警告C:警告:参数列表内声明了'struct'

我刚刚在C语言中发现了一个奇怪的问题,令人感到困惑。在C语言中,可以在结构体声明之前使用它的指针。这是一个非常有用的功能,因为在处理指向它的指针时,声明是无关紧要的。但是,我只是发现一个极端的情况(令人惊讶地),这是不正确的,而且我无法真正解释原因。在我看来,这似乎是语言设计中的一个错误。


采取以下代码:


#include <stdio.h>


#include <stdlib.h>



typedef void (*a)(struct lol* etc);


void a2(struct lol* etc) {


}


int main(void) {

        return 0;

}

给出:


foo.c:6:26: warning: ‘struct lol’ declared inside parameter list [enabled by default]

foo.c:6:26: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]

foo.c:8:16: warning: ‘struct lol’ declared inside parameter list [enabled by default]

为了解决这个问题,我们可以简单地做到这一点:


#include <stdio.h>


#include <stdlib.h>


struct lol* wut;


typedef void (*a)(struct lol* etc);


void a2(struct lol* etc) {


}


int main(void) {

        return 0;

}

无法解释的问题现在由于无法解释的原因而消失了。为什么?


请注意,这个问题是关于语言C的行为(或者可能是gcc和clang的编译器行为),而不是我粘贴的特定示例。


编辑:


我不会接受“声明的顺序很重要”作为答案,除非您也解释了为什么C会在函数参数列表中第一次警告不要使用struct指针,但允许在任何其他上下文中使用它。为什么那可能是个问题?


达令说
浏览 1573回答 3
3回答

慕尼黑的夜晚无繁华

这是因为,在第一个示例中,该结构先前未定义,因此编译器尝试将对该结构的第一个引用视为定义。通常,C是声明顺序很重要的语言。您使用的所有内容均应事先以某种能力进行适当声明,以便编译器可以在其他上下文中引用它时对其进行推理。这不是语言设计中的错误或错误。相反,我认为这是为了简化第一个C编译器的实现而做出的选择。前向声明使编译器可以一次通过串行转换源代码(只要知道一些信息(例如大小和偏移量))。如果不是这种情况,则编译器只要遇到无法识别的标识符,便能够在程序中来回移动,从而要求其代码发射循环更加复杂。

慕妹3146593

编译器警告你一个向前声明的struct lol。C允许您执行以下操作:struct lol;&nbsp; &nbsp; &nbsp;/* forward declaration, the size and members of&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;struct lol are unknown */这在定义自引用结构时最常用,但是在定义从未在头文件中定义的私有结构时也很有用。由于存在后者,因此可以声明接收或返回指向不完整结构的指针的函数:void foo(struct lol *x);但是,像您一样,仅在函数声明中使用未声明的结构,将被解释为局部不完整声明,struct lol其范围受函数约束。这种解释是由C标准强制执行的,但是它没有用(无法构造struct lol传递给函数的方法),并且几乎肯定不是程序员想要的,因此编译器警告。
打开App,查看更多内容
随时随地看视频慕课网APP