为什么我可以通过指针转换而不是C中的全局变量来更改本地const变量?

udp*_*nil 4 c pointers constants

我想通过使用指针来改变常量的值.

请考虑以下代码

int main()
{
    const int const_val = 10;
    int *ptr_to_const = &const_val;

    printf("Value of constant is %d",const_val);
    *ptr_to_const = 20;
    printf("Value of constant is %d",const_val);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,常量的值被修改.

但是当我尝试使用全局常量的相同代码时,我遇到了运行时错误.Windows崩溃记者正在开放.在此语句"*ptr_to_const = 20;"中打印第一个printf语句后,可执行文件暂停

请考虑以下代码

const int const_val = 10;
int main()
{
    int *ptr_to_const = &const_val;
    printf("Value of constant is %d",const_val);
    *ptr_to_const = 20;
    printf("Value of constant is %d",const_val);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该程序使用codeblocks IDE在mingw环境中编译.

谁能解释一下发生了什么?

sth*_*sth 16

这是一个常数,无论如何你都在使用一些技巧来改变它,因此会导致未定义的行为.全局常量可能在只读内存中,因此无法修改.当您尝试这样做时,您会收到运行时错误.

在堆栈上创建常量局部变量,可以对其进行修改.所以你在这种情况下改变常数,但它可能仍会导致奇怪的事情.例如,编译器可以在各个地方使用常量的值而不是常量本身,因此"更改常量"在这些地方不会显示任何效果.


Ale*_*ell 7

它在只读内存中!

基本上,您的计算机使用两级页表系统将虚拟地址解析为物理地址.随着宏大的数据结构,一个特殊的位表示页面是否可读.这很有用,因为用户进程可能不应该过度编写自己的程序集(尽管自修改代码很酷).当然,他们可能也不应该过度编写自己的常量变量.

您不能将"const"函数级变量放入只读内存中,因为它位于堆栈中,它必须位于读写页面上.但是,编译器/链接器会看到你的const,并通过将它放在只读内存(它是常量)中帮你一个忙.显然,覆盖将导致内核的各种不满,他们会通过终止它来消除对流程的愤怒.