外部声明中的警告

rea*_*ays 12 c

#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;
Run Code Online (Sandbox Code Playgroud)

我定义了一个头文件(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)
{

}
Run Code Online (Sandbox Code Playgroud)

以上两个文件都在同一目录中.我编译了上面的文件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
Run Code Online (Sandbox Code Playgroud)

我想知道当我将变量声明为extern并且我已经标记为粗体时为什么我会将其作为警告对此有任何想法,如果有人想要在剩余错误上分享任何其他事情,请告诉我.

AnT*_*AnT 37

虽然您的代码包含许多相当严重且明显的错误(已在其他答案中涵盖),但您在问题标题中添加的警告是完全无意义的无意义警告.GCC编译器因发布无用警告而臭名昭着.这些警告中的许多似乎都源于某人的无能和完全没有根据的信念,即做某事"某种程度上是错误的",而实际上并没有任何问题.

在您的情况下,警告由触发

extern int stack_counter = 0;
Run Code Online (Sandbox Code Playgroud)

宣言.显然,警告的"作者"认为extern说明者应该保留用于非定义的声明.在这种情况下,初始化程序的存在= 0将声明转换为定义(因此正式使其成为extern可选).尽管如此,它并没有错误,事实上,extern这里可能非常欢迎强调这一事实stack_counter是一个全局变量.

同样,您是否需要全局变量是一个不同的问题,同样,您的代码包含大量其他错误.但是你似乎关注的警告并不值得.只需在编译器设置中禁用此警告(并且,请向GCC团队写一封关于它的粗略信函).

  • 公平地说,这是一个可以预示(并帮助解决)链接器错误(多重定义)的警告.例如......在TU 1中,一个人创建一个全局并分配它,然后在TU 2中我们复制声明,然后将`extern`添加到该声明中.与extern一起出现的初始化使得extern意味着不同的东西,从而导致创建这个变量的两个实例并且链接器barfs ...这并不是说你的观点有任何不太有效,但这可能是存在的警告...... (13认同)
  • @StevenLu:所以,GCC会在错误发生之前发出警告,然后无论如何都会在链接阶段发生错误.好东西. (3认同)
  • 预期用途是在一个文件中具有单个外部*定义*,例如“int a;”,并在其他文件中具有一个或多个*声明*“extern int a;”。使用“extern”可以表明该变量是在其他位置“定义”的(可能在同一个文件中,但最有可能在不同的源文件中)。`extern int a = 5` 违反了这个习惯用法。 (3认同)
  • 好吧,像if(x = 1){...}这样的代码是完全合法的,但是通常会受到警告. (2认同)
  • @alecov 这就是为什么你真的应该总是使用`-Werror`。GCC 在编译无效代码方面非常出色,但最好完全防止编译不正确的代码。 (2认同)
  • @AndreyPortnoy 不,这不是预期用途。`extern` 说明符的预期用途是提供一个标识符*外部链接*。在这个角色中,它可以在声明和定义中统一使用。在前一种上下文中,它“导入”名称,在后一种上下文中,它“导出”名称。它是完全对称的。后一种用法在 C 中是多余的(与 C++ 相对),但它仍然是正确的。 (2认同)
  • 有趣的事实:`clang`也有这个警告:https://clang.llvm.org/docs/DiagnosticsReference.html#wextern-initializer (2认同)

nmi*_*els 6

头文件中的extern声明允许除定义变量之外的模块使用它.如果它应该被定义为int stack_counter = 0并存在于stack.c中,那么将其定义为并extern stack_counter在头文件中放置一个.

在stack.c的第6行,您没有为sroot定义存储类.由于它在标题中被删除,我认为你打算输入snode sroot=NULL.

修复这些,然后实现stackpush(确保它不返回void)并按顺序处理其余的警告.请注意,在C中,您必须使用函数的前向声明(使用原型)或在使用之前定义函数.该cstack函数可能应该是文件中的最后一个函数.


Dav*_*ger 5

我刚刚收到 gcc 的警告,这是一个简单的修复。stack_counter 不应在标头中初始化,而应在包含它的源文件中初始化。所以标题应该只使用:

extern int stack_counter;
Run Code Online (Sandbox Code Playgroud)

然后在包含该标头的一个源文件的全局范围内声明并初始化 stack_counter:

int stack_counter = 0;
Run Code Online (Sandbox Code Playgroud)