gpt4 book ai didi

c - 奇怪的编译器警告 C : warning: ‘struct’ declared inside parameter list

转载 作者:行者123 更新时间:2023-11-30 16:53:05 27 4
gpt4 key购买 nike

我刚刚发现了 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 会在函数参数列表中首次使用结构指针时发出警告,但允许在任何其他上下文中使用它。为什么这会成为一个问题?

最佳答案

要理解编译器提示的原因,您需要了解有关 C“struct”的两件事:

  • 一旦命名它们,它们就会被创建(作为已声明但尚未定义的类型),因此 struct lol 的第一次出现会创建一个声明
  • 它们遵循与普通变量相同的“声明范围”规则

(struct lol { 声明然后开始定义结构,它是 struct lol;struct lol * 或其他不开括号在“声明”步骤之后停止。)

已声明但尚未定义的结构类型是 C 所谓的“不完整类型”的实例。只要您不尝试跟随指针,您就可以使用指向不完整类型的指针:

struct lol *global_p;
void f(void) {
use0(global_p); /* this is OK */
use1(*global_p); /* this is an error */
use2(global_p->field); /* and so is this */
}

换句话说,您必须完成该类型才能“跟随指针”。

无论如何,请考虑使用普通 int 参数的函数声明:

int imin2(int a, int b); /* returns a or b, whichever is smaller */
int isum2(int a, int b); /* returns a + b */

此处名为 ab 的变量在括号内声明,但这些声明需要避开,以便下一个 函数声明不会提示它们被重新声明。

同样的事情也会发生在 struct 标记名上:

void gronk(struct sttag *p);

struct sttag 声明了一个结构,然后该声明被清除,就像 ab 的声明一样。但这会产生一个大问题:标签消失了,现在您无法再次命名结构类型!如果你写:

struct sttag { int field1; char *field2; };

定义了一个新的、不同的struct sttag,就像:

void somefunc(int x) { int y; ... }
int x, y;

在文件级范围定义新的不同的xy,与somefunc中的不同。

幸运的是,如果您在编写函数声明之前声明(甚至定义)结构体,则原型(prototype)级声明“引用回”外部作用域声明:

struct sttag;
void gronk(struct sttag *p);

现在,两个 struct sttag 都是“相同的”struct sttag,因此当您稍后完成 struct sttag 时,您就完成了gronk 的原型(prototype)中也有一个。

<小时/>

关于问题编辑:当然可以以不同的方式定义 struct、union 和 enum 标签的操作,使它们从原型(prototype)“冒泡”到其封闭范围。这样问题就迎刃而解了。但它并不是这样定义的。由于是 ANSI C89 委员会发明了原型(prototype)(或者实际上是从当时的 C++ 窃取的)原型(prototype),因此您可以将其归咎于他们。 :-)

关于c - 奇怪的编译器警告 C : warning: ‘struct’ declared inside parameter list,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41034033/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com