代码之家  ›  专栏  ›  技术社区  ›  Praxeolitic

什么时候抛弃const是合法的还是非法的?(gcc、clang和MSVC)

  •  3
  • Praxeolitic  · 技术社区  · 8 年前

    什么时候抛弃 const

    在许多情况下 康斯特 只是为了用户的利益而由编译器强制执行的注释。这个问题是在抛弃时提出的 康斯特 严格来说是非法的,C99标准的哪一部分禁止这样做(如果有)?

    我怀疑这在某些情况下是非法的,因为我观察到了这一点 康斯特 全局范围中的函数指针有时由gcc内联。如果这些函数指针可以在程序中进行合法修改,则此优化将无效。此外,我很确定我已经阅读了关于何时抛弃的解释 康斯特 在StackOverflow上是非法的,但我就是找不到它。(我想答案是 康斯特 只能在变量最初未声明为 康斯特 .)

    我标记了这个C99,因为我希望这是C99标准中规定的东西,但如果答案可以解释C99的gcc、clang和MSVC实现的常见行为,那么这对我来说也足够了。

    特别适用于C标准

    1 回复  |  直到 8 年前
        1
  •  13
  •   Community raghavsood33    4 年前

    抛弃警察从来都不是违法的。你可以自由合法地做任何你想做的事。但试图 修改 去掉常量后的指向对象可能会导致未定义的行为(也可能不会,取决于具体情况)。

    C99明确指出:

    6.7.3类型限定符

    5.

    (C11中为6.7.3/6)。

    注意 const 在C(和C++)中,用于两个独立且非常不同的角色:const限定 物体本身 以及 到对象。

    const int a = 42;  // `a` is a const-qualifiet object
    
    int b = 5;         // `b` is not const-qualified
    const int *p = &b; // `*p` is a const-qualified access path to `b`
    

    *(int *) p = 6; // nothing formally wrong with it
    

    这正是我们有能力摆脱语言中的稳定的原因。

    *(int *) &a = 43; // undefined behavior
    

    原因很简单-const对象可以物理上位于只读内存中。即使不是,编译器仍然可以自由编译代码,前提是对象的值永远不会改变。

    这意味着,在声明中

    const int *const cp = &b;
    

    康斯特 康斯特 ,如果条件正确,则可以覆盖。但是第二个 康斯特 是一个“硬” 康斯特 这是不能被推翻的。

    所以,当你说 康斯特 是一个简单的注释,为用户的利益,由编译器强制执行”,这仅适用于访问路径的常量限定。当涉及对象本身的常量限定时,通常不仅仅是纯概念编译器强制执行的“注释”。