【问题标题】:Why can't I directly assign an int to an int pointer like this: int *p = 6;?为什么我不能像这样直接将 int 分配给 int 指针:int *p = 6;?
【发布时间】:2017-12-11 12:36:57
【问题描述】:

错误:从 'int' 到 'int*' 的转换无效
int *q = 8;

工作正常。
*q = 6;

为什么我不能像这样直接将 int 分配给 int 指针:int *q = 6;我可以在下一行安全地分配它吗?

【问题讨论】:

  • 初始化与赋值
  • 尽量不要写多语言源文件。做起来很困难,而且结果不是任何一种选择的语言。
  • 我可以在下一行安全地分配它 - 不!指针未初始化。你不能取消引用它。
  • 鉴于这比副本有更多的答案和更高的分数,最好关闭另一个帖子作为这个的副本而不是关闭这个。

标签: c++ c pointers initialization variable-assignment


【解决方案1】:

* 符号在您的 sn-p 中用于两个不同的目的。第一次使用它作为类型声明int * 的一部分,声明一个指向int 的指针。第二次用于取消引用指针*q,调用间接运算符。

*也可以用来调用乘法运算符*q = *q * *q;

要将值分配给指针指向的整数,您需要取消引用它。并且将除 0 以外的整数值分配给指针本身(这就是 int *q = 8; 正在做的事情)需要 reinterpret_cast,因此会出现此错误。

【讨论】:

  • “两个不同的目的”实际上是不真实的。我们来看一下两个指针的定义:int *p, *q;。如果* 属于int,您将定义两个指针为int* p, q /*wrong*/; 这是C 兼容性的不幸残余,因为在其他上下文中,例如std::vector<int*>,它 的一部分输入..
【解决方案2】:

语句int *q 定义了一个“指向整数的指针”类型的变量,因此初始化需要是指针值,而不是整数值。 所以int *q = 8int *q; *q = 8 不同(这将是未定义的行为,因为它取消引用未初始化的指针),但更像int *q; q = 8,这使得误解更加透明。

【讨论】:

    【解决方案3】:

    因为类型不匹配。

    6 本身不是指针类型的值,它是一个整数,因此不能直接存储在指针中。

    当您执行*q = 6 * dereferences 指针时,类型变为int(或者更确切地说是左值int,即可以分配给的东西)。

    【讨论】:

      【解决方案4】:

      如果你像这样重写它:

      int* q = 8; 
          *q = 6;
      

      那么你可以看到*有两个不同的用途。

      【讨论】:

      • 怎么样?此代码不会在符合标准的 C 编译器上编译。
      【解决方案5】:

      因为它们完全不同。第一个是带有初始化表达式的变量定义,即initialization(指针本身):

      int *         q                      = 8;
      ~~~~~         ~                      ~~~
      type is int*; name of variable is q; initialized with 8
      

      第二个是赋值(指针指向的对象):

      *q                              = 6;
      ~~                              ~~~
      dereference on q via operator*; assign the resulting lvalue pointed by q to 6
      

      并且,int *p = 6; 表示定义一个名为p 的变量,其类型为int*,并用6 对其进行初始化,但由于6 不能用于直接初始化指针而失败(即错误“从 'int' 到 'int*' 的无效转换”)。

      【讨论】:

        【解决方案6】:

        在您的第一条语句中,您声明并初始化指向int 类型值的指针(在同一行)。在您的第二个语句中,您正在更改指针指向的值。两种不同的东西。您所拥有的是初始化,然后是分配。不要让* 迷惑你。

        【讨论】:

          【解决方案7】:

          这个:

          int *q = 8;
          

          是一个初始化。它初始化q(指针),而不是*q(它指向的东西)。用赋值而不是初始化等价地写这个看起来像:

          int *q;
          q = 8;
          

          所以你看它没有意义。 (当然是不允许的——int 不是指针)

          只是为了确定,如果你写的话:

          int *q;
          *q = 8;
          

          这是语法正确的,但是未定义的行为。您的指针未指向int 类型的对象,它未初始化并且可能指向某个无效位置。写在那里,任何事情都有可能发生。

          【讨论】:

          • 不,它在语法上不正确。您不能将整数分配给指针,这违反了简单分配的约束。 (初始化遵循同样的规则)
          • 我指的是第一行,它不会编译,因为它违反了约束。
          • @Lundin 我认为我的文字足够清晰,可以理解“syntactically correct”指的是最后一个 sn-p,如果你仔细阅读的话。
          • 仍然无法编译第一行。它不会像您声称的那样初始化指针,因为它不会编译。
          • @Lundin 谈到了 syntax,稍后会详细说明。我不认为这是有效的代码。
          【解决方案8】:

          因为它不是有效的C,就这么简单。具体来说,它违反了赋值运算符的约束,因为指向指针的整数或指向整数的指针不是“简单赋值”的有效形式(C11 6.5.16.1)。

          您可以通过添加显式强制转换在整数和指针之间进行转换。然而,结果并不能保证有效:指针和整数可能有不同的表示,并且可能存在对齐问题。

          *q = 6; 的情况下,您将一个 int 分配给一个 int,这当然很好(假设指针指向某处分配的内存)。

          【讨论】:

            【解决方案9】:

            当您编写
            int *q = 8; 时,这意味着您声明了一个指针 q 并使用整数 8 初始化了一个指针。但是 q 作为一个指针需要一个 address value,因此您会收到说明不兼容的错误。
            而当您在声明后写入
            *q=8 时,这意味着您正在取消引用q 指向的地址并将值写入该位置。这里q 指向int,因此您将8 写入q 指向的位置的整数值。没错。如果 q 未初始化为指向正确的位置,这也可能导致运行时出错。

            【讨论】:

            • 不能用整数初始化指针,因为初始化遵循“简单赋值”的规则。您必须先将整数转换为指针。
            • 谢谢。我明确指出问题在于整数被分配给了一个指针。
            【解决方案10】:

            在这里,将值8 分配给int* 类型的对象。这意味着q 指向内存上的地址8

             int *q = 8;
            

            等同于

            int *q;
            q = 8;
            

            不等同于

            int *q;
            *q = 8;
            

            非法,因为它涉及违反约束

            相关堆栈溢出问题:Is it possible to initialize a C pointer to NULL?

            【讨论】:

            • 您的“是非法的,因为它涉及违反约束”是指 OP 的代码 - 它们格式化您的帖子的方式看起来您可能在谈论您的最后一个代码 sn-p (这不是一个约束违规)
            【解决方案11】:

            试试

            int *q = new int(8);
            

            但这里通常不需要使用指针。如果必须使用指针,请使用智能指针shared_ptr<int>uniqe_ptr<int>

            【讨论】:

              【解决方案12】:

              在这种情况下,您将值 8 分配给指针 *q,它在初始化期间将不起作用,内存地址是唯一的,当时无法分配,但您可以在 *q 初始化后创建内存块后设置一次。

              【讨论】:

                【解决方案13】:

                一个指针变量保存一个地址,或某物的“位置”。因此,指针保存的值是一个内存地址。当你说:

                int *q = 6;
                

                您正在创建一个指向 int 的指针变量,并告诉它指向存储在地址 6 中的 int 值,这(可能)不是您真正想要的。

                一个指针变量应该指向一些包含你想要访问的实际数据的内存地址。例如:

                int x = 5;
                int *q = &x;
                

                这将创建一个包含值 5 的变量 (x)。 下一行创建一个包含 x 地址的指针变量。您已将指针变量“q”设置为 int 变量“x”的地址。

                现在您可以通过执行以下操作查看“x”处的内容:

                int y;
                y = *q;
                

                这表示“获取 q 指向的内容,并将其存储在 y 中”。最终效果是 y 将设置为 5。

                int x = 5;     // create variable x and set it to 5
                int *q = &x;   // create int pointer variable, set it to the address of x
                int y;         // create variable y
                y = *q;        // take the value pointed to by q, and store it in y
                

                例如,如果变量 x 位于内存位置 1234,并且您查看存储在 'q' 中的值,它将是 1234,即 x 的地址。 当您说“y = *q”时,您是在说“取存储在地址 1234 中的值,并将该值放入 y”。由于内存位置 1234 是“x”,并且“x”被分配了值 5,因此值 5 将存储在地址 1234 处。

                y = *q;
                

                将获取存储在地址 1234 中的值并将 y 分配给该值,从而使 y 为 5,这是存储在 x 中的值,这是 q“指向”的值。

                这可以缩短为:

                int x = 5;
                int *q = &x;
                int y = *q;
                

                【讨论】:

                • 这仅回答了问题的前半部分,而不是第二个问题:“我可以在下一行安全地分配它吗?”
                猜你喜欢
                • 1970-01-01
                • 2021-03-23
                • 1970-01-01
                • 2019-05-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-03-26
                相关资源
                最近更新 更多