【问题标题】:Changing the value of a const pointer更改 const 指针的值
【发布时间】:2009-04-21 04:58:02
【问题描述】:

我有以下代码:

void TestFunc(const void * const Var1, const float Var2) { *(浮点数*)Var1 = Var2; }

看起来我正在更改 const 指针指向的 const 对象的值(感谢Sharptooth),这是不允许的。事实上,我试过的编译器都没有发出警告。这怎么可能?

【问题讨论】:

    标签: c pointers constants


    【解决方案1】:

    正如其他人所提到的,就表达式而言,演员表删除了目的地的“常量”。当您使用强制转换时,编译器会根据强制转换处理表达式 - 只要强制转换本身有效(并且 C 风格的强制转换几乎是大锤子)。这就是您没有收到错误或警告的原因。你本质上是在告诉编译器,“保持安静,我知道我在做什么,这就是你应该如何对待事情的方式”。事实上,强制转换可能是程序员让编译器停止发出警告的第一选择。

    您的赋值表达式可能是也可能不是未定义的行为。 如果实际指向的对象不是 const,则允许丢弃 const。

    但是,如果指向的对象是 const,那么您就有未定义的行为。

    void TestFunc(const void * const Var1, const float Var2)
    {
      *(float*)Var1 = Var2;
    }
    
    
    int
    main(void)
    {
        float x = 1.0;
        const float y = 2.0;
    
        TestFunc( &x, -1.0);    // well defined (if not particularly great style)
        TestFunc( &y, -2.0);    // undefined behavior
    
        return 0;
    }
    

    你正在踏入危险的水域......

    一般情况下(我确信也有例外),C/C++ 中支持强制转换以使表达式处理对象的真实情况,这是明确定义的行为。

    标准中涵盖了这种特殊行为,主要是通过删除 const 限定符的强制转换(或其他东西)来修改 const 对象的语句是未定义的。推论是对非常量对象做同样的事情并不是未定义的。 C++ 标准中给出的一个例子说明了这一点。

    C90 6.5.3 - 类型限定符 (C99 6.7.3):

    如果尝试通过使用来修改使用 const 限定类型定义的对象 具有非 const 限定类型的左值,行为未定义。

    C++ 7.1.5.1 cv 限定符

    指向 cv 限定类型的指针或引用不需要实际指向或引用 cv 限定对象,但它被视为就好像它确实指向或引用了一个 cv 限定对象;即使引用的对象是非常量对象并且可以通过其他访问路径进行修改,也不能使用 const 限定的访问路径来修改对象。 [注意:cv 限定符是 由类型系统支持,因此如果不进行强制转换(5.2.11),它们就不能被颠覆。 ]

    除了可以修改任何声明为 mutable (7.1.1) 的类成员外,任何修改 const 的尝试 对象在其生命周期 (3.8) 中会导致未定义的行为。

    ...

    [示例:

    ...

    int i = 2;            //not cv-qualified
    const int* cip;       //pointer to const int
    cip = &i;             //OK: cv-qualified access path to unqualified
    *cip = 4;             //ill-formed: attempt to modify through ptr to const
    
    int* ip;
    ip = const_cast<int*>(cip);   //cast needed to convert const int*to int*
    *ip = 4;                      //defined: *ip points to i, a non-const object
    
    const int* ciq = new const int (3);   //initialized as required
    int* iq = const_cast<int*>(ciq);      //cast required
    *iq = 4;                              //undefined: modifies a const object
    

    【讨论】:

    • 感谢您的详细解释。您是否碰巧有参考,其中记录了 C 语言?我能找到的只是 C++ 中对 const_cast 的引用。
    • 我从标准中添加了相关材料。
    • 我很欣赏它。非常感谢!
    【解决方案2】:

    你改变的是指针指向的对象,而不是指针的值。

    C 风格的强制转换类似于 const_cast 并从指针中移除 const 修饰符。编译器现在没有什么可抱怨的了。

    【讨论】:

      【解决方案3】:

      强制转换是合法的,但行为未定义。

      【讨论】:

      • 这对我来说似乎是一个令人困惑的答案。使用强制转换可能是也可能不是未定义的行为,具体取决于它的用途。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      • 2012-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多