C中指针变量的冲突类型(错误)

(1)

#include  #include  int a = 10, b = 20 , c = 30, d, e, *pa, *pb, *pc; d= 10; e= 100; pa = &a; pb = &b; int main() { printf("%i, %i, %i, %i", pa, pb, d, e); return 0; } 

(2)

 #include  #include  int a = 10, b = 20 , c = 30, d, e, *pa, *pb, *pc; d= 10; e= 100; int main() { pa = &a; pb = &b; printf("%i, %i, %i, %i", pa, pb, d, e); return 0; } 

为什么在初始化主函数(1)之外的指针变量pa和pb时会出现错误? 当pa和pb在主函数内部时,它可以很好地工作(2) 。 为什么我可以初始化主函数(d,e)之外的正常变量而不是指针变量?

我在CodeBlocks中收到的错误消息是:pa的文件类型冲突。 先前的pa声明在这里:第4行。

可执行代码必须进入函数内部。 这是因为C程序的执行流程始于调用main()

int a = 10; 被称为声明 ,它们可能被认为是在程序开始之前“发生”。 通常,编译器将生成所有全局变量数据的块,并在启动程序时加载它。

当你写d = 10; 在文件范围内,这被视为int d = 10; 。 由于在文件范围内不允许语句,因此它不是赋值语句。 编译器认为这是一个声明,你打算写int但想通过将其保留来保存输入。

这被称为隐式int ,C89有它,尽管它在C99中被删除了。

所以当你写pa = &a; ,implicit int使其成为int pa = &a; 并且你得到一个错误,因为你已经声明了类型为int * pa ,然后再使用int ,它们是不同的类型。

然而,将变量声明为int然后将其重新声明为int (就像对de所做的那样)只要第一个没有初始化器就可以了。 这称为暂定定义

为了避免这一切,请确保任何不是声明的代码都在函数内部。 你可以写文件范围:

 int a = 5; int *pa = &a; 

等等。


另外, printf("%i, %i, %i, %i", pa, pb, d, e); 导致未定义的行为 。 %i说明符必须与int匹配。 要解决此问题,您需要传递(int)pa而不是pa等,或使用%p说明符。

你可以初始化main()之外的指针,但声明需要随后定义。 检查代码:

 ` #include  #include  int a = 10, b = 20 , c = 30, d, e; d= 10; e= 100; int *pa = &a; int *pb = &b; int main() { printf("%p, %p, %i, %i", pa, pb, d, e); return 0; } 

`

分配和初始化是不同的操作。

 int *pa = &a; 

是一个带初始化程序的声明,可以在函数或文件范围内发生。

 int *pa; pa = &a; 

是一个声明,后跟一个赋值语句。 赋值语句(与任何其他可执行语句一样)必须在函数体内发生。

我猜这是一个较旧的编译器仍然允许隐式int声明,所以它正在处理语句

 d = 10; e = 100; 

作为使用初始化器定义声明,而不是赋值语句。 它将之前的de声明视为非定义声明,并且因为它们被声明为int ,所以没有冲突。

相比之下,这些陈述

 pa = &a; pb = &b; 

被初始化器处理为隐式int声明,但由于您之前将它们声明为int * ,因此编译器会抱怨类型不匹配。

注意:输出语句有问题。

 printf("%i, %i, %i, %i", pa, pb, d, e); 

如果要在papb 指向的变量中打印整数值,则必须在printf调用中取消引用它们:

 printf("%i, %i, %i, %i", *pa, *pb, d, e); 

如果要打印存储在papb的指针值,则必须使用%p转换说明符:

 printf("%p, %p, %i, %i", (void *)pa, (void *)pb, d, e); 

以及将指针值转换为void * (这几乎是你在C中显式地将指针转换为void *的时候)。