【问题标题】:Conflicting types for pointer variable in C (Error)C中指针变量的类型冲突(错误)
【发布时间】:2015-10-13 02:51:36
【问题描述】:

(1)

#include <stdio.h>
#include <stdlib.h>

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 <stdio.h>
#include <stdlib.h>

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 在 main 函数中时,它工作得非常好(2)。为什么我可以在主函数(d,e)之外初始化普通变量而不是指针变量?

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

【问题讨论】:

  • (我不确定)但我相信您不能将语句放在您的 main 之外执行,就像您希望它们在您的 main 中那样执行。虽然你可以声明变量。我相信当您编写pa = &amp;a 时,编译器并不知道您已经声明了pa。此外,如果您不提供数据类型,则会自动将其视为int,因此,当您编写pa 时,编译器会将其设为int pa(不考虑您之前的声明),然后您尝试分配指向您的 int 的指针,这就是它给您错误的原因!
  • 内存分配只发生在main之后
  • @purpletech 这不是分配,全局变量不驻留在堆空间中
  • d= 10;pa = &amp;a; 等行正在重新声明这些变量,而不仅仅是设置它们的值……只要类型与之前的声明匹配,这在文件范围内是允许的。由于您没有在这些行中给出类型,因此假定它是 int,因此它与 de 的早期声明匹配,但与 papb 不匹配。

标签: c variables pointers compiler-errors


【解决方案1】:

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

 #include <stdio.h>
 #include <stdlib.h>

 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;
 }

【讨论】:

  • 但是这样你就从第一行删除了声明。是否可以像常规变量一样在一行中声明它并在另一行(main 之外)对其进行初始化?
  • 在您的代码中,我们刚刚看到不同行中的单独声明和单独定义在 main 之外不起作用 - 我仍然没有理由这样做。
【解决方案2】:

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

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

当您在文件范围内写入 d = 10; 时,这将被视为 int d = 10; 。由于在文件范围内不允许使用语句,因此它不是赋值语句。编译器认为这是一个声明,您打算在其中编写 int 但希望通过省略它来节省输入。

这被称为 implicit int 并且 C89 有它,尽管它在 C99 中被删除了。

因此,当您编写 pa = &amp;a; 时,隐式 int 将其变为 int pa = &amp;a; 并且您会收到错误,因为您已将 pa 声明为 int * 类型,然后再次使用 int,它们是不同的类型。

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

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

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

等等。


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

【讨论】:

  • 更像:“可执行代码必须进入函数内部。这是因为...... 这就是它在 C 中的方式,”C++ 程序也有 main,然而函数之外可以有可执行代码(全局初始化器和构造器)。 C 编译器在main 之前具有运行代码的扩展,例如 GCC 的构造函数属性(以及适当的运行时支持)。
  • @Kaz 这是一道 C 题
  • @Kaz 我的答案,被发布到一个 C 问题,应该被理解为只适用于 C。我已经更新了这句话来澄清。
【解决方案3】:

赋值和初始化是不同的操作。

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 *)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-27
    • 2014-03-10
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多