是否可以更改const全局变量的值?

时间:2013-12-28 11:19:14

标签: c pointers

是否可以更改const全局变量或外部全局变量的值?通过指针?

你可以改变const局部变量的值。

8 个答案:

答案 0 :(得分:2)

C11:6.7.3类型限定符:

  

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

换句话说,您可以说const限定对象不可修改

答案 1 :(得分:2)

我猜这将取决于。例如,对于这个程序

#include <stdio.h>

const int val = 12345;

int main(void)
{
    printf("%d\n", val);

    int *tmp = (int *)&val;
    *tmp = 678;

    printf("%d\n", val);
    return 0;
}

程序(在Linux上使用gcc编译)会产生分段错误。但是如果'const'行在main函数内移动并改为创建局部变量,它似乎确实有效(没有启用任何优化)。

在使用objdump检查可执行文件时,变量val位于名为.rodata的部分中,当程序尝试以某种方式更改内存时导致分段错误。

答案 2 :(得分:2)

虽然可能可能似乎在某些C实现中更改了const对象的值,但这种外观可能是一种错觉,并且很难在受控制中执行因为:

  • 当尝试修改使用const定义的对象时,C标准未定义行为。
  • 修改可能看起来有效,因为它会导致对象的某些用途发生变化而不会导致其他用途发生变化。例如,编译器可以将const对象的值构建到其他表达式中,以便xconst int a = 10; int x = 2*a;的初始化将x初始化为20而不引用{{ 1}}。可能会发生{strong>某些使用a引用为其分配的内存并使用更改后的值,如果您设法更改它,而a的其他用途同一程序以内置方式使用原始值。显然,这会导致一个非常混乱的程序。
  • 修改可能在一个C实现中“起作用”但在另一个C实现中失败,因为这两个实现以不同的方式管理a个对象。
  • 修改可能在您的程序中起作用,但在以明显不相关的方式更改源代码时会失败,例如插入需要编译器将一些临时值保存到堆栈的其他计算。更改编译器选项时,您的程序可能也会失败,尤其是在启用优化时。

在许多C实现中,常量全局数据存储在标记为只读的内存区域中。尝试修改它会导致异常,通常会终止您的程序。可以要求操作系统更改此保护,然后修改内存。但是,这样做可能会产生编译器产生的副作用,假设恒定数据不会发生变化。

当您能够修改自动对象(例如一个定义的而不是函数体)而不是静态对象(例如在任何函数外定义的对象)时,可能是因为静态对象保持有恒定的全局数据,标记为只读,但自动对象保留在堆栈中。堆栈包含不同内容的混合,在今天的处理器上不可能将堆栈的小部分标记为只读,而其他部分可写。因此,您可以通过物理访问来修改const个自动对象。但是,您仍然没有C标准的许可证;行为未定义,可能会有隐藏的副作用会破坏您的程序。


另外,const并不总是意味着对象是不变的。当一个对象定义const时,C标准不会定义尝试修改它的行为。但是,可以添加 const指针并稍后将其删除。例如,这是合法代码:

const

这种行为是必需的,因为C语言最初是在没有int a = 3; const int *b = &a; int *c = (int *) b; *c = 4; 的情况下设计的,因此它的语义不是为了适应它而设计的,并且在某些情况下如果const始终不能正常工作执行。

答案 3 :(得分:1)

您仍然可以尝试使用mprotect功能将数据部分更改为RW而不是RO。

http://linux.die.net/man/2/mprotect

请参阅Self modifying code always segmentation faults on Linux

由于它是您自己的程序段,因此您不需要任何权限。此代码可能有效:

#include <stdio.h>
#include <sys/mman.h>

const int c = 1;

int main(int argc, char *argv[])
{
    if(mprotect(&c, sizeof(int), PROT_READ | PROT_WRITE) == 0) c = 5;
    printf("%d\n", c);
    return 0;
}

答案 4 :(得分:0)

Const变量不能改变,这就是为什么它们是const。 其他变量可以更改,如果您可以访问变量本身,则不需要指针

答案 5 :(得分:0)

不能改变常数的值,因为它被称为常数

答案 6 :(得分:0)

问题没有意义:变量没有值,只有对象表达式

您无法更改常量对象的值。

但是,您可以使用某种合适的“常量引用”类型的变量来评估不同的东西:

int a = 10;

const int * const b = &a;

int main()
{
    print(b);
    *a = 20;
    print(b);
}

答案 7 :(得分:0)

是的,你可以:

#include <stdio.h>

const volatile int global = 10;

int main(void)
{
    int *ptr = (int*) &global;

    printf("Initial value of global : %d \n", global);
    *ptr = 100;
    printf("Modified value of global: %d \n", global);
    return 0;
}

由于volatiletake a look

,它可能会有效

但正如其他人所建议的那样,不要这样做