重新定义全局范围中的指针

在这个问题中,我对这个看似基本的C方面感到非常困惑。考虑这两行代码:

int *ptr; *ptr = 2; 

gcc将发出以下警告:

 main.cpp:4:1: warning: data definition has no type or storage class [enabled by default] *ptr = 2; ^ main.cpp:4:2: warning: type defaults to 'int' in declaration of 'ptr' [enabled by default] *ptr = 2; ^ main.cpp:4:8: warning: initialization makes pointer from integer without a cast [enabled by default] *ptr = 2; ^ 

ptr被默认为什么类型, intint* (如,是ptr指针,还是int )? 如果是这样,这是否意味着ptr指向地址2,或者是否保持不变? 我会认为它已经改变了,因为它崩溃了,除非你给ptr一个有效的地址。

 int i = 5; int *ptr; *ptr = &i; int main(){ printf("%d", *ptr); // 5 } 

我知道未定义行为的可能性,你不应该忽略警告,但我试图看看这里发生了什么。

有关上下文,请参阅此答案下的注释链。

以下是正在发生的事情:由于您显示的两行是在文件范围内(而不是本地范围),因此两行都被视为声明 ,而不是声明和赋值语句。 这是因为文件范围内可能没有语句 – 只允许声明和定义。

旧C规则允许int类型的声明完全省略类型。 因此,第二行是

  • ptr声明/定义
  • …这是一个指针,因为它有一个星号
  • …它也是指向int的指针,因为缺少类型。

最后一条规则非常陈旧,并且已在ANSI语言标准版本中弃用。 这就是你得到警告的原因。 如果您将代码更改为

 int *ptr; int *ptr = &i; 

你的代码将编译并运行( 演示 )。

现在还有一个问题:编译器怎么不抱怨重复声明? 事实certificate,编译器会将多个相同的声明视为同一个声明,只要它们彼此完全相同即可。