更改 const 指针的值

发布于 2024-07-17 08:23:23 字数 207 浏览 3 评论 0原文

我有以下代码:

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

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

I have the following piece of code:

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

It looks like I am changing the value of the const object the const pointer points to (thanks sharptooth), which should not be allowed. Fact is, none of the compilers I tried issued a warning. How is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

っ〆星空下的拥抱 2024-07-24 08:23:23

正如其他人提到的,就表达式而言,强制转换消除了目的地的“常量”。 当您使用强制转换时,编译器会根据强制转换来处理表达式 - 只要强制转换本身有效(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 对象的语句来涵盖这种特定行为,这些语句是未定义的。 推论是,对非常量对象执行相同操作并不是未定义的。 C++ 标准中给出的示例清楚地说明了这一点。

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

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

C++ 7.1.5.1 cv 限定符

对 cv 限定类型的指针或引用实际上不需要指向或引用 cv 限定对象,但它会被视为指向或引用; 即使引用的对象是非常量对象并且可以通过其他访问路径进行修改,const 限定的访问路径也不能用于修改对象。 [注:简历限定符是
由类型系统支持,以便在不进行强制转换的情况下无法颠覆它们(5.2.11)。 ]

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

...

[示例:

...

int i = 2;   //不符合简历资格 
  常量 int* cip;   //指向const int的指针 
  cip = &i;   //OK:cv限定到非限定的访问路径 
  *cip = 4;   //格式错误:尝试通过ptr修改为const 

  int* ip; 
  ip = const_cast(cip);   //将 const int* 转换为 int* 需要进行强制转换 
  *ip = 4;   //定义: *ip 指向 i,一个非常量对象 

  const int* ciq = 新 const int (3);   //按要求初始化 
  int* iq = const_cast(ciq);   //需要强制转换 
  *智商=4;   //undefined: 修改一个const对象 
  

As others mentioned, the cast removes the 'constness' of the destination as far as the expression is concerned. When you use a cast the compiler treats the expression according to the cast - as long as the cast itself it valid (and C-style casts are pretty much the big hammer). This is why you don't get an error or warning. You're essentially telling the compiler, "be quiet, I know what I'm doing, this is how you should treat things". In fact, casts are probably the #1 way for programmers to get the compiler to stop issuing warnings.

Your assignment expression may or may not be undefined behavior. It is permitted to cast away constness if the object actually pointed to is not const.

However, if the object pointed to is const, then you have undefined behavior.

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;
}

You're treading dangerous waters...

In general (I'm sure there are exceptions), casting so that expressions treat objects as they really are is supported, well-defined behavior in C/C++.

This particular behavior is covered in the standards mostly by statements that modifying a const object through a cast (or something) that removes the const qualifier is undefined. The inference is that doing the same for a non-const object is not undefined. An example given in the C++ standard makes this clear.

C90 6.5.3 - Type Qualifiers (C99 6.7.3):

If an attempt is made to modify an object defined with a const-qualified type through use
of an lvalue with non-const-qualified type, the behavior is undefined.

C++ 7.1.5.1 The cv-qualifiers

A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path. [Note: cv-qualifiers are
supported by the type system so that they cannot be subverted without casting (5.2.11). ]

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
object during its lifetime (3.8) results in undefined behavior.

...

[Example:

...

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
动次打次papapa 2024-07-24 08:23:23

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

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

You change the object the pointer points to, not the pointer value.

C-style cast acts like a const_cast and removes the const modifier off the pointer. The compiler now has nothing to moan about.

我三岁 2024-07-24 08:23:23

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

The cast is legal, but the behaviour is undefined.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文