【问题标题】:Understanding the Warning and Compilation Error while Initializing and Declaring Pointer Variable [duplicate]了解初始化和声明指针变量时的警告和编译错误 [重复]
【发布时间】:2015-04-01 18:39:14
【问题描述】:

请看下面的代码sn -p -

int main(){

   int  *i_ptr = 5;
   printf("%d", *i_ptr); 

   return 0;
}

这里我试图声明和初始化一个指针变量i_ptr。它在编译正常时给了我以下警告 -

警告:初始化使指针从整数而不进行强制转换 [默认启用]

但是当我要执行代码时,它给了我以下错误 -

分段错误(核心转储)

我知道这样做的正确方法 -

int n = 5;
int *ptr = &n;  

现在我有一些问题 -

1.虽然第一个代码在执行时失败,为什么它没有给出编译错误,而不是警告?

2.我们可以像这样初始化和声明指针变量吗 -

int n = 5 // both declaration and initialization of int type variable n  

提前致谢。

【问题讨论】:

  • int *i_ptr = 5 表示地址,而不是地址的内容,是 5。它不会报错,因为 5 是有效地址。
  • "我们能不能像这样初始化和声明指针变量-" - 是的,你已经知道了:int *ptr = &n;
  • 你可能想要的是int *i_ptr = new int(5);
  • 这不应该在 C++ 中编译,句号。
  • @immibis,这意味着我们也可以写 int *ptr = &5 ?

标签: c++ c pointers


【解决方案1】:
  1. 虽然第一个代码在执行时失败,为什么它没有给出编译错误,而不是警告?

错误和警告之间的区别取决于您传递给编译器的标志。

除了通过-Werror 将警告变为错误之外,最好在开发过程中使设置更加偏执(-Wall-Wextra,甚至可能使用 Clang 的-Weverything)(您可能不应该这样做) t 发货代码时默认设置)。

  1. 我们可以像这样初始化和声明指针变量吗

指针变量存储地址,你需要声明一个可寻址的东西,你可以在其中存储值 5。

从 C99 开始,可以使用复合文字而不是命名变量:

int *p = &(int){ 5 };

【讨论】:

    【解决方案2】:

    * 在您的代码中具有不同的含义。

    这不是指针解引用而是指针声明,所以你声明一个指针并为其分配一个整数,指针会将整数存储为它指向的地址。

    这可能是未定义的行为,因为您不知道 5 是否是有效地址,而且很可能不是。

    如果你把声明和初始化分开,很明显代码有不同的含义,例如

    int *pointer; /* here the `*' is used for pointer declaration */
    int  value;
    
    pointer  = &vaule; /* we store the address of value */
    *pointer = 5; /* we dereference the pointer and write to that location */
    /* ^ here the `*' is used for pointer dereference */
    
    printf("%d\n", value * 5); /* this will print 25 */
    /*                   ^ here the `*' is used for multiplication */
    

    现在你看到我说你的代码令人困惑,因为

    int *pointer = 5;
    

    似乎等同于

    *pointer = 5;
    

    但事实并非如此。

    【讨论】:

      【解决方案3】:
      1. int *n = 5 在技术上没有任何问题。它是一个有效的指针,指向地址为 5 的内存,这就是它允许您编译它的原因。它出现段错误的原因是您的程序无权访问此内存。

      【讨论】:

      • “没有错”?在 C 和 C++ 语言中,用非零整数初始化指针值是完全非法的。代码格式不正确。这种初始化(如果您出于某种原因需要它)需要显式转换。
      • 我绝不会为初始化指向静态整数值的指针辩护。我只是说“技术上”没有问题。这就是它被编译的原因,也是编译器打印关于它的警告的原因。
      • @MartinKalcok:它在技术上是错误的,因为它不遵循 ISO 标准指定的 C 语言规则(参见 C11 6.5.16.1,它也适用于根据 6.7.9 § 11)
      【解决方案4】:

      当你在做的时候

      int  *i_ptr = 5;
      

      您将地址 5 分配给 i_ptr。但由于此地址不属于您的程序,因此当您取消引用 i_ptr 时,它会给您分段错误。仅尝试访问属于您的程序的那些内存位置。

      【讨论】:

        【解决方案5】:

        编译器不需要让它出错,所以它不会。

        您要查找的语法是:int *i_ptr = new int(5);

        这将为整数分配足够大的新内存,将值设置为 5,并将i_ptr 设置为指向该内存。记忆完成后记得做delete i_ptr;

        【讨论】:

          【解决方案6】:

          您的代码在 C 和 C++ 语言中都是非法的。不允许使用整数值初始化指针。这个

          int *i_ptr = 5;
          

          是非法的。正如其他一些答案似乎暗示的那样,它不是“将地址 5 分配给指针”。上述初始化在标准 C 和 C++ 语言领域中显然是不可编译的。

          您收到的诊断消息表明您的代码中有错误。之后,C 和 C++ 都不会对您的代码的含义做出任何保证,即您的代码既不是 C 也不是 C++。

          不要忽略编译器发出的诊断消息。 C 和 C++ 不区分“警告”或“错误”。任何诊断消息都应被视为潜在错误。您可以在看似“单纯的警告”的情况下识别错误。使用 GCC,您还可以尝试使用 -pedantic-errors 选项将错误报告为错误。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-09-21
            • 2016-06-02
            • 2011-06-17
            相关资源
            最近更新 更多