C语言 外部声明中的警告
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4268589/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
warning in extern declaration
提问by reality displays
#include<stdio.h>
#include<stdlib.h>
#define GREY 1
#define BLACK 0
#define WHITE 2
typedef struct node * graph;
typedef struct stack * snode;
graph cnode(int data); //cnode is to create a node for graph
void cgraph(void);
struct node {
int data, color;
struct node *LEFT, *RIGHT, *TOP, *DOWN;
};//this structure defines a node of the graph
struct stack {
struct stack *priv;
struct cgraph *graph_node;
};// this is to define a structure which should hold node of a structure
extern snode sroot;
I defined a header file (declaration.h) as above and following is a c program(stack.c) I am making which would be used in the library I am developing
我定义了一个头文件(declaration.h),下面是我正在制作的 ac 程序(stack.c),它将在我正在开发的库中使用
#include<declarations.h>
void cstack (graph temp);
void stackpush(snode stemp);
extern int stack_counter = 0;
sroot=NULL;
void cstack (graph gtemp) //cstack is to create stack
{
snode spriv,some;
if (stack_counter==0)
{
sroot=stackpush(gtemp);
spriv=sroot;
stack_counter++;
}
else{
some=cstacknode(gtemp);
some->priv=spriv;
spriv=some;
}
}
//struct stack is representing a stack
//struct node is representing a node in graph
snode cstacknode (graph gtemp)
//this function should create a node of the stack which should be storing the graph node as a pointer
{
snode an;
an=(snode)malloc(sizeof(snode));
an->graph_node=gtemp;
an->priv=NULL;
return an;
}
void stackpush(snode stemp)
{
}
both the above files are in same directory.
I compiled the above file stack.c
cc -I ./ stack.cI following warnings
以上两个文件都在同一目录中。我编译了上面的文件 stack.c
cc -I ./ stack.c我遵循警告
stack.c:4: warning: ‘stack_counter' initialized and declared ‘extern'
stack.c:6: warning: data definition has no type or storage class
stack.c:6: error: conflicting types for ‘sroot'
./declarations.h:21: note: previous declaration of ‘sroot' was here
stack.c:6: warning: initialization makes integer from pointer without a cast
stack.c: In function ‘cstack':
stack.c:12: warning: passing argument 1 of ‘stackpush' from incompatible pointer type
stack.c:3: note: expected ‘snode' but argument is of type ‘graph'
stack.c:12: error: void value not ignored as it ought to be
stack.c:13: warning: assignment makes pointer from integer without a cast
stack.c:17: warning: assignment makes pointer from integer without a cast
stack.c: At top level:
stack.c:27: error: conflicting types for ‘cstacknode'
stack.c:17: note: previous implicit declaration of ‘cstacknode' was here
stack.c: In function ‘cstacknode':
stack.c:32: warning: assignment from incompatible pointer type
I want to know when I declared a variable as extern which I have marked bold why do I get that as a warning any thoughts on that and if some one wants to share any other thing on remaining errors then let me know.
我想知道当我将一个变量声明为 extern 时,我已将其标记为粗体,为什么我将其作为警告,对此有任何想法,如果有人想分享有关剩余错误的任何其他内容,请告诉我。
回答by AnT
While your code contains a number of rather serious and obvious errors (already covered in other answers), the warning you put into the title of your question is a completely superfluous meaningless warning. GCC compiler is notorious for issuing useless warnings. Many of those warnings seem to be derived from someone's incompetent and completely unsubstantiated belief that doing something is somehow "wrong", while in reality there's nothing wrong with it.
虽然您的代码包含许多相当严重且明显的错误(已在其他答案中涵盖),但您在问题标题中添加的警告完全是多余的毫无意义的警告。GCC 编译器因发出无用警告而臭名昭著。许多警告似乎来自某人无能且完全没有根据的信念,即认为做某事在某种程度上是“错误的”,而实际上并没有错。
In your case the warning is triggered by
在您的情况下,警告是由
extern int stack_counter = 0;
declaration. Apparently, the "author" of the warning believed that externspecifier should be reserved for non-defining declarations. In this case the presence of initializer = 0turns the declaration into a definition (and thus formally makes that externoptional). Nevertheless, there's no error in it and, in fact, externmight be quite welcome here to emphasize the fact that stack_counteris intended to be a global variable.
宣言。显然,警告的“作者”认为extern应该为非定义声明保留说明符。在这种情况下,初始化程序的存在= 0将声明转换为定义(因此正式使其成为extern可选的)。尽管如此,它并没有错误,事实上,extern在这里强调stack_counter旨在成为全局变量的事实可能非常受欢迎。
Again, whether you need a global variable here or not is a different question and, again, your code contains a massive number of other errors. But the warning you seem to focus your attention on is not really worth it. Just disable this warning in compiler settings (and, please, write a rude letter about it to GCC team).
同样,这里是否需要全局变量是一个不同的问题,同样,您的代码包含大量其他错误。但是你似乎把注意力集中在警告上并不值得。只需在编译器设置中禁用此警告(并且请写一封粗鲁的信给 GCC 团队)。
回答by nmichaels
The extern declaration in your header file lets modules other than the one in which the variable is defined use it. If it's supposed to be defined as int stack_counter = 0and live in stack.c, define it like that and put an extern stack_counterin the header.
头文件中的 extern 声明允许定义变量的模块以外的模块使用它。如果它应该被定义为int stack_counter = 0并存在于 stack.c 中,请像这样定义它并将 anextern stack_counter放在标题中。
On line 6 of stack.c, you didn't define a storage class for sroot. Since it's externed in the header, I assume you meant to type snode sroot=NULL.
在 stack.c 的第 6 行,您没有为 sroot 定义存储类。由于它位于标题中,因此我假设您打算键入snode sroot=NULL.
Fix those, then implement stackpush (make sure it doesn't return void) and deal with the rest of your warnings in order. Note that in C, you have to either use forward declarations of functions (with prototypes) or define your functions before they're used. The cstackfunction should probably be the last function in the file.
修复这些,然后实现 stackpush(确保它不返回 void)并按顺序处理其余的警告。请注意,在 C 中,您必须使用函数的前向声明(带有原型)或在使用之前定义函数。该cstack函数可能应该是文件中的最后一个函数。
回答by eigenslacker
Clang still issues a warning for this. The line
Clang 仍然为此发出警告。线
extern int counter = 0;
will trigger the warning:
将触发警告:
warning: 'extern' variable has an initializer [-Wextern-initializer]
警告:'extern' 变量有一个初始化器 [-Wextern-initializer]
This warning is not important, as definingthe variable with
这个警告并不重要,因为定义变量
int counter = 0;
still yields a static duration and external linkage by default. Indeed, if no storage-class specifier is provided, the defaults are:
默认情况下仍会产生静态持续时间和外部链接。实际上,如果没有提供存储类说明符,则默认值为:
externfor all functionsexternfor objects at file scopeautofor objects at block scope
extern对于所有功能extern对于文件范围内的对象auto对于块范围内的对象
There is also something called a tentative definitionwhich is an external declaration without an initializer, and either without a storage-class specifier or with the specifier static.
还有一种叫做暂定定义的东西,它是一个没有初始值设定项的外部声明,要么没有存储类说明符,要么没有说明符static。
A tentative definitionis a declaration that may or may not act as a definition. If an actual external definition is found earlier or later in the same translation unit, then the tentative definition just acts as a declaration.
一个初步的定义是,可能会或可能不会作为一个定义的声明。如果在同一翻译单元中较早或较晚找到实际的外部定义,则暂定定义仅充当声明。
So the following line
所以下面这行
int counter;
is a tentative definitionthat declares and defines counterwith the implicit initializer = 0(or, for array, structure, and union types, = {0}).
是一个临时定义,它声明和定义counter隐式初始值设定项= 0(或者,对于数组、结构和联合类型,= {0})。

