微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

了解未定义的常量行为

如何解决了解未定义的常量行为

我已经编写了下面的代码

{
    const int i = 24;
    int* ptr{};
    ptr = (int*)&i;
    std::cout << i << std::endl;
    *ptr = 13;
    std::cout << i << std::endl;
    std::cout << *ptr << std::endl;
}

在我的调试器中,我看到 i 的值已更改为 13,但在将 i 设置为 13 后打印 i 时的输出仍为 24。

24
24
13 

提前致谢!

解决方法

在 C 和 C++ 中,const 表示变量是只读的。

The CV qualifiers:

有两个 cv 限定符,const 和 volatile

你应该这样写:

#include <iostream>

using namespace std;

int main (void) {
    const int i = 24; // not cv-qualified
    const int* ptr; // pointer to const int
    ptr = &i; // OK: cv-qualified access path to unqualified
    //*ptr = 12;  // ill-formed: attempt to modify through ptr to const
    printf("%p\n%p\n",ptr,&i);
    std::cout << i << std::endl;
    std::cout << *ptr << std::endl;
}

或者删除 const 如果您希望能够修改该值:

#include <iostream>

using namespace std;

int main (void) {
    int i = 24;
    int* ptr;
    ptr = &i;
    *ptr = 12; // Now OK
    printf("%p\n%p\n",&i);
    std::cout << i << std::endl;
    std::cout << *ptr << std::endl;
}

您不能更改 const 变量的值,您可能仍然可以这样做,但是您将程序暴露给未定义的行为:

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

只要将“i”放置在 x86 架构中非只读的堆栈或寄存器中,您的程序仍然可以在 x86 架构上运行。 .text 部分(程序集)是内存只读的区域。


要说明未定义的行为以及您通过写入只读内存区域而暴露自己的风险,请参见以下示例:

#include <iostream>

using namespace std;

int main (void) {
    const int i = 24;
    int* ptr;
    ptr = (int *)&i;
    *ptr = 12;  // UB
    std::cout << "value at ptr: " << *ptr << std::endl;
    std::cout << "value at i: " << i << std::endl;
    printf("%p address of ptr\n%p address of i\nIs it witchcraft?\n\n",&i);

    char s[64] = "Ave Caesar,Morituri te salutant\0";
    std::cout << s << std::endl;
    ptr = (int *)s;
    *ptr = 0x20657661; // OK write " eva" at address of s,reversed because of little endianness.
    std::cout << s << " (modified string)" << std::endl; // now with lowercase 'a'
    printf("%p address of ptr\n%p address of s\n\n",s);

    const char *str  = "Ave Caesar,Morituri te salutant\0"; // in .text segment
    ptr = (int *)str;
    printf("%p address of ptr\n%p address of s\n\n",str);
    std::cout << str << " (read-only)" << std::endl;
    *ptr = 0x20657661; // attempt to write on read-only memory -> segmentation fault
    std::cout << str << std::endl;
    printf("%p\n%p\n",s);
    return 0;
}

输出:

value at ptr: 12
value at i: 24
0x7ffcb13df0cc address of ptr
0x7ffcb13df0cc address of i
Is it witchcraft?

Ave Caesar,Morituri te salutant
ave Caesar,Morituri te salutant (modified string)
0x7ffcb13df0e0 address of ptr
0x7ffcb13df0e0 address of s

0x55b0572f3db0 address of ptr
0x55b0572f3db0 address of s

Ave Caesar,Morituri te salutant (read-only)
Segmentation fault (core dumped)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。