更改const指针的值

时间:2009-04-21 04:58:03

标签: c pointers const

我有以下代码:

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

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

3 个答案:

答案 0 :(得分:11)

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

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

但是,如果指向的对象是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对象的语句是未定义的。推断是对非const对象执行相同操作并非未定义。 C ++标准中给出的一个例子清楚地说明了这一点。

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

  

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

C ++ 7.1.5.1 cv-qualifiers

  

对cv限定类型的指针或引用实际上不需要指向或引用cv限定的对象,但它被视为具有;即使引用的对象是非const对象并且可以通过某些其他访问路径进行修改,也不能使用const限定的访问路径来修改对象。 [注意:cv-qualifiers是   由类型系统支持,以便在不进行铸造的情况下不会破坏它们(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

答案 1 :(得分:2)

您更改指针指向的对象,而不是指针值。

C样式转换就像一个const_cast,并从指针中删除 const 修饰符。编译器现在没有任何呻吟声。

答案 2 :(得分:1)

演员表是合法的,但行为未定义。