【问题标题】:Assigning to const int *分配给 const int *
【发布时间】:2009-02-27 11:00:51
【问题描述】:
void main()
{
const int * a;
*a = 5;
}

gcc 错误:分配只读位置。

那么,如何在不使用其他变量的情况下分配给 *a? 像上面这样的声明有什么用?

【问题讨论】:

  • 为什么会有“不使用其他变量”的限制?
  • 因为不然太简单了:再创建一个int *b,赋值b = a,然后*b = 5会修改*a。
  • 当然很简单。但这是第二个问题的答案:“像上面这样的声明有什么用?”。哦,您的“b = a”并不完全正确:它将 const 转换为非 const。你宁愿 a = b。

标签: c pointers constants


【解决方案1】:
const int * a;

从右到左阅读声明。[见注释] 你得到什么? a* 即指向 int 的指针,即整数 const 即常量。简而言之,变量a 指向一个您无法更改其值的整数。至少,不是通过a。指针是否真的不可变是另一个问题。但事实是,你不能用a修改*a

const 是您对自己的承诺:我永远不会尝试使用指向 const 的指针来修改指针。编译器只为您提供支持。

如果您真的想要写入指针,您需要一个非常量指针,例如:

int *a;
*a = 42; /* this is fine */

还有来自bortzmeyer 的非常好的评论:(我想我会跳过这个以保持简单:)

你也可以把const放在*之后(正如你所说,声明应该从右到左阅读)。

他的意思是这样的:

const int *a;

没有区别
int const *a;

(还记得,从右到左的阅读规则吗?) 但与:

int * const p;

阅读它,我们得到:p 是一个const(-ant) *(指针) 到int(-eger)。翻译:一旦您将p 设置为指向一个整数,您就无法重新安装它(即写入它以使其指向另一个整数——使p 成为常​​量),但是您可以非常写入指针很多(指针不是恒定的)。

注意:这里是来自Darron的“规则”:

“声明应该从右到左阅读”是一种简化——如果有括号,它们应该从内到外阅读。除非括号表示函数调用。真正的规则是“把它当作一个表达式对待;如果我应用这些运算符,我最终会得到这个简单的类型”。

如果不是 bortzmeyerDarron,这个答案真的会少很多肉 - 谢谢!

PPS:(我保证这将是最后一次编辑。嗯,希望如此!)

void main() 不是 C 或 C++ 中 main 的标准签名。在您认识您之前不要使用它,或者(更重要的是)您的代码将永远不必前往另一个宇宙。

【讨论】:

  • 你在我之前到达那里 - 你糟糕的整体声音:)。我打算给出从 {int *i;} 到 {const int * const i;} 的例子以及如何阅读它们,但生活实在是太短了。
  • 你也可以把 c​​onst 放在 * 之后(就像你说的,声明应该从右到左阅读)。
  • @Binary Worrier: 不用担心,会发生什么,会发生什么 :) 对我来说,这主要是发生了
  • “const 是你对自己的承诺”——这是对 const 用途的一个很好的总结。不错。
  • “声明应该从右到左阅读”是一种简化——如果有括号,它们应该从内到外阅读。除非括号表示函数调用。真正的规则是“把它当作一个表达式对待;如果我应用这些运算符,我最终会得到这个简单的类型”。
【解决方案2】:

一个说明 Ruben Bartelink 出色解释的例子:

#include <stdlib.h>

int main()
{
  int * const a = malloc(sizeof(int));
  if (a == NULL) 
    return 1;
  *a = 3;
  free(a);
  return 0;
}

在这里,a 是常量(因此必须初始化)但不是 *a(可能是 OP 想要的)。

【讨论】:

  • 现在符合 gcc -Wall 和夹板 :-)
【解决方案3】:

让我把你的问题换成简单的英文。

  • 如果我向编译器保证我不会写入变量a指向的值,我该如何写入变量a指向的值?

答案:至少在本地更改承诺。

int main()
{
    const int * a;
    *((int *) a) = 5;
}

希望上面的措辞清楚地表明这通常是一个坏主意。

【讨论】:

  • 在我的帖子中为你们 +1。请更改void main()——这是非标准的(读起来很糟糕)。
  • 当您从问题开始时会发生这种情况。 :-)
  • 根据 C/C++ ANSI/ISO 标准,转换左值是非法的!一些编译器虽然支持它作为非标准扩展,但不鼓励使用它。
  • 您可以使用临时变量克服强制转换限制。必须这样做应该更清楚地表明您所做的事情并不理想。
【解决方案4】:

你的意思是int * const,而不是const int *。在一种情况下,指针是 const,另一种情况下它指向的东西是 const。你也可以const int * const。阅读一些关于 const_cast 的文章并没有什么坏处,它们应该很好地涵盖了这一点。

【讨论】:

    【解决方案5】:

    const 的点不是你不能分配给它的吗?虽然,我不记得在 const 指针的情况下,它指向的值是否不能更改,或者指针的地址。或两者。我的猜测是两者都无法改变。

    它也可能是您尝试写入未初始化内存的一般警告(或错误,取决于编译器设置)。

    正确的是(我假设):

    void main()
    {
       const int* a = new int(5);
    }
    

    【讨论】:

    • gcc 拒绝识别“新”。所以,我必须使用 C++?
    • 不,只使用 malloc() 而不是 new。
    【解决方案6】:

    没有回答“如何在不使用其他变量的情况下分配给 *a?”但只有“像上面这样的声明有什么用处?”。

    承诺不修改指向的值。正如评论中所讨论的那样,如果您对允许自己使用该构造的方式进行了限制,您可以得出它没有用的结论。但是,如果您允许自己使用整个 C 语言,那么您可以找到用途。想想strcmp的原型之类的。

    【讨论】:

      【解决方案7】:

      问题是你创建了一个指针,但它实际上并没有指向任何东西,所以当你取消引用它(或尝试写入它引用的位置)时,你会得到一个错误。

      【讨论】:

      • 不,这不是唯一的问题:重新阅读原始消息,这是一个编译错误。
      • 是的 - 大多数现代编译器能够在编译时检测到这些明显的问题,而不是在运行时,尤其是在一个简单的情况下,例如引用的那个 - 你不需要运行程序来看到那里将是一个错误。
      • 再一次,问题不在于 OP 问题中缺少动态分配。这是一个错误,是的,但即使你修复它,OP 指出的主要问题仍然存在。
      猜你喜欢
      • 2013-10-15
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多