C compiler ignores 'static' for declaration of struct
在C语言中,如果我声明这样的结构:
1 2 3
| static struct thing {
int number;
}; |
并编译它(在本例中使用gcc),编译器将打印此警告:
warning: 'static' ignored on this declaration
[-Wmissing-declarations]
为什么会这样?
我的目的是使结构保持静态,以便另一个文件可以声明自己的thing,如果需要的话。
- 型它是一种数据类型,只在定义它的编译单元中可见。这就是为什么要在跨编译单元共享它时将其放在头中的原因。
- 型@nicomp:所以你是说一个结构声明,或者任何与此相关的数据类型声明,已经有了我想要的行为,即不在全局命名空间中,不使用"static",只要它不放在头中?
- 型单词static适用于用它声明的变量,而不是类型。例如:static struct timeval startw,这里startw被认为是静态的,而不是timeval。参考
- 型是的,我是这么说的。不能"extern"用户定义的数据类型。
- 型而且,据我所知,在C中没有名称空间,但是有人会匆匆忙忙地转到XYZ标准文档,然后直接发送给我。
- 型@c中的nicomp"namespace"只是指通常可见的对象/函数/typedef名称、struct或enum关键字后面的标记、函数中的标签和结构成员是不冲突的标识符的单独分类。
- 型>静态结构int number;thing;类似这样的内容是有效的。
- 型消息是否在头文件中声明?
- 型另一个建议是使用typedef struct { int number; } thing;。
- 型据我所知,标准没有定义操作代码的行为。没有像"static被忽略"这样的文本,除非它定义了含义。因此,这将是不明确的行为疏忽。
- 型@我不确定这是否属于"行为的任何明确定义的遗漏"条款。标准说明了关键字对包含关键字的声明声明声明的对象或函数的影响,对于此声明,声明的对象和函数的数量恰好为零。我注意到clang++,g++,和msvc都同意代码是可以接受的,但值得警告。
- 型@这是一个C问题。你能指出哪一条将涵盖本规范中static的行为吗?
- 型@很抱歉,我指的是C模式下的clang、gcc和msvc(我在测试中使用了这个模式,只是在这里输入了错误的名称)。不,我不能引用任何直接支持我的解释的东西。我只是模糊地不相信这是一种"行为"(尽管"行为"当然可以涵盖翻译的某些方面,而不仅仅是执行)。
- 型@m.m或者实际上,有6.7/6"声明说明符由一系列说明符组成,这些说明符表示链接、存储持续时间和声明者表示的实体类型的一部分。"声明中的说明符确实表示链接和存储持续时间,并影响所有零声明者的类型。至少对于"部分类型"短语来说,这是可以接受的…
- 型@我就是这么说的。
如果不定义实际对象,则无法定义存储。
1 2 3
| static struct thing {
int number;
}obj1,obj2; |
可以,而且:
1 2 3 4 5
| struct thing {
int number;
};
static struct thing x,y; |
结构标记(和typedef名称)没有链接,这意味着它们不在翻译单元之间共享。您可以使用术语"private"来描述这一点。两个不同的单位定义自己的struct thing是完全可以的。
只有当它试图对具有外部链接的函数进行跨单元调用,而外部链接接受从该函数派生的struct thing或类型时,才会出现问题。通过确保只有通过头文件中的原型(即不要使用本地原型)调用具有外部链接的函数,可以将发生这种情况的可能性降到最低。
在这种方式下,不能像对函数或对象那样使用static来控制类型的链接,因为在C类型中,无论如何都没有链接。
"全局命名空间"不是您想要的术语。c将对象和函数的名称描述为具有"外部链接"(如果相同的名称可以在不同的翻译单元中声明为表示相同的内容(如函数的默认值),"内部链接"(如果相同的名称可以在相同的翻译单元中重新声明为表示相同的内容(如标记为static的声明),或)当一个声明与任何其他声明(如在函数体中定义的变量)命名不同的对象或函数时,没有链接。(大致来说,翻译单元是一个*.c文件及其包含的头文件的内容。)但这些都不适用于类型。
所以,如果您想要使用一个对一个源文件本质上是私有的结构类型,只需在那个源文件中定义它。然后,您不必担心相同名称的另一个用法会与您的名称冲突,除非可能有人将其添加到源文件包含的头文件中。
(而且,如果C++用户遇到这个问答,请注意C++中的规则非常不同。)
- 我很惊讶你没有提到范围就试图报道这件事。链接仅适用于对象,而不适用于类型。操作试图隐藏类型,因此它们必须控制其范围。
- @jwdonahue范围与这个问题无关。另外,您的"链接仅适用于对象"声明是不正确的;它适用于对象和函数。也不清楚为什么你试图指出链接不适用于类型,因为这个事实是这个答案的基础。也许你可以自己写答案
- @当然,在某些情况下,它可能有助于在函数中定义结构。但是,如果要在多个函数和/或静态函数的参数或返回类型中使用该结构,则这不是一个选项。