为什么下面的代码会出现编译错误“error:conflictingtypesfor'ptr'”?静态int val=33;int*ptr//=&瓦尔;ptr=&val;

为什么下面的代码会出现编译错误“error:conflictingtypesfor'ptr'”?静态int val=33;int*ptr//=&瓦尔;ptr=&val;,c,pointers,static,int,C,Pointers,Static,Int,我的目标是使静态变量“val”可用于不同的.c文件,仅用于实验 所以我创建了一个全局指针,它保存静态变量的地址,通过这个全局指针,我试图访问另一个文件中静态变量的值 但是, 给我一个错误 如果我这样做的话,它是有效的 static int val=33; int *ptr = &val; 为什么?在做什么 在全局范围中定义全局变量,对于编译器,ptr的隐式类型是ptr=&val;所以这与int*不兼容。您不能在全局范围内分配,这就是为什么ptr=&val;不是先前定义的ptr赋值,而是

我的目标是使静态变量“val”可用于不同的.c文件,仅用于实验

所以我创建了一个全局指针,它保存静态变量的地址,通过这个全局指针,我试图访问另一个文件中静态变量的值

但是,

给我一个错误

如果我这样做的话,它是有效的

static int val=33;
int *ptr = &val;
为什么?

在做什么

在全局范围中定义全局变量,对于编译器,ptr的隐式类型是ptr=&val;所以这与int*不兼容。您不能在全局范围内分配,这就是为什么ptr=&val;不是先前定义的ptr赋值,而是具有初始值的全局变量的定义

将代码放在本地范围内没有问题,例如

int main()
{
  static int val=33;
  int *ptr;
  ptr = &val; /* an assignment of ptr */
}

编译没有问题

您使用的是一个旧的或质量差的编译器,它假定int为缺少的类型

在文件范围中,一个表达式语句,如ptr=&val;不是标准C的一部分。编译器正试图将其视为声明语句。为此,它假定一种int类型,就像语句是:

int ptr = &val;
由于ptr以前声明为int*,因此此新声明与int类型冲突,并且编译器报告存在冲突类型

C 2018 6.7.2 2规定了声明的约束条件:

在每个声明的声明说明符中,以及在每个结构声明和类型名称的说明符限定符列表中,应至少给出一个类型说明符


当违反约束时,编译器应发出有关该约束的诊断消息。因此,一个好的编译器会警告类型说明符丢失,而不仅仅是生成的默认类型与先前的声明冲突。

gcc 6.3.0版是一个质量差的编译器吗?^^这是我手上的那个吗raspberrypi@bruno:它很旧,没有正确的开关,质量很差。我建议至少使用-Wmost-std=c11,并且在上面使用-Wpedantic。但是,即使没有开关,它也发出警告:“警告:数据定义没有类型或存储类”和“警告:类型在'ptr'声明中默认为'int'”。这主要是一个笑话,你鼓吹一个令人信服的,我在编译时使用-pedantic-Wall-Wextra,正如你在我的回答中看到的那样,当我向编译器解释时-将代码放在块作用域中会破坏OP在外部对象中提供地址的目标。他们应该使用第二个代码,在文件范围初始化。或者,他们可以将声明保留在文件范围内,但将赋值放在块范围内。@EricPostPhischil I添加了第二个案例,以解释相同形式可能具有不同的含义,这取决于它的位置,在当前情况下,定义全局变量和赋值局部变量之间的区别-@苏拉沃什:事实证明这是一场灾难。将显示的代码放在一个文件中,并使用编译器进行编译,将生成显示的消息;取决于它在哪里,看看我的答案
int main()
{
  static int val=33;
  int *ptr;
  ptr = &val; /* an assignment of ptr */
}
int ptr = &val;