在全局范围内重新定义指针 我对C这个看似基本的方面完全混淆了。考虑这两行代码: int *ptr; *ptr = 2;

在全局范围内重新定义指针 我对C这个看似基本的方面完全混淆了。考虑这两行代码: int *ptr; *ptr = 2;,c,C,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: init

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
被默认为,
int
int*
(例如,
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;
您的代码将编译并运行()


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

后续错误可能是由以前的声明引起的。只需为指针分配内存或将其指向有效内存。当编译器发现问题时,它会尽力找出最好的方法。应用了警告后,这会发出警告,并尽可能地进行。这可能会导致后续警告。最好关注第一个警告并纠正第一个是代码未定义的行为,即使它是出于这些原因工作的?我相信“未定义的行为”意味着“语言规范没有告诉编译器应该如何工作”,“它工作”意味着“您使用的编译器做出了您想要的选择”@remyabel它没有未定义的行为。该标准尊重关于声明的旧规则,没有隐式地考虑显式类型
int
,因此它与
int*ptr=&i*ptr=2
实际上像
int*ptr=2
一样工作,并且不推荐使用?所以无论如何,不要做那样的事。