C语言 const变量能不能修改?

本文详细解析了在Ubuntu平台x86gcc环境下,局部const和全局const变量的存储位置(.text vs .rodata)、是否可修改,以及对它们的操作行为。通过实例和代码展示,揭示了const变量并非完全不可更改,仅受编译器控制和权限限制。
摘要由CSDN通过智能技术生成

 笔者在跟同事讨论变量存放的分区问题时,讨论到了const标识符所标记的变量能不能修改这个问题。

按直观理解,const关键字标识的变量,意味不能修改的变量,引申理解,猜测其可能存放在.rodata分区(只读)。

========================================================================

来实际操作验证一下,一看便知。

环境:选用Ubuntu平台,x86 gcc工具。

一、局部的const变量

代码验证:首先是局部的const变量

#include <stdio.h>
#include <string.h>

//const int global_const_vol = 84;
char *s = "abcde";
int main()
{
        const int const_vol = 11; 

        return 0;
}

C语言的字符串变量会放在rodata段,我们以此作为参考

gcc -c选项可以只将.c文件编译成目标文件(.o),而不进行链接,使我们分析自己写的代码少了很多冗余代码,方便分析。

objdump -xsd 可以将目标文件中各个段的内容都打印出来。

 我们只需要找我们定义的两个变量就好了,const_vol,s。

可以看到.data段中啥也没有,我们的s变量被放在了rodata段,存放的就是我们初始化的abcde变量,而const变量不知道去哪里了。

 答案是在.text段(代码段)里,对比以下代码和dump结果便知。

include <stdio.h>
#include <string.h>

//const int global_const_vol = 84; 
char *s = "abcde";
int main()
{
//        const int const_vol = 11; 

        return 0;
}

 编译 && dump

 很明显,.text段中的c745fc0b这块数据丢了。

并且.data段的大小没变化

我们可以得出结论:本环境下的局部const变量存放于text段中,程序运行时会将此变量放置于栈区。

既然在栈中,那其本身就应该处于可以修改的内存位置

我们先直接对其进行修改。

int main()
{
        const int const_vol = 11;

        const_vol = 100;

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

 编译

 报错,那显然不能执行了。

直接对其地址进行修改呢?

int main()
{
        const int const_vol = 11; 
        int *pointer = &const_vol;
            
        *pointer = 100;

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

编译器只进行了警告,我们的const变量也成功被改写了;

结论:对局部的const变量地址进行操作,完全可以重写const变量中的内容;

二、全局的const变量

首先第一个问题,全局const变量存放的位置。

代码:

const int global_const_vol = 10; 
char *s = "abcde";
int main()
{
        return 0;
}

 编译成.o文件,并ojbdump:

 

 可以看到rodata中除了abcde以外,多了0a000000。

这是由于是小端字节序的文件,正确的顺序应该是0000000a,即10,我们的全局const变量。

得出结论:全局const变量是存放于rodata区的。

那能否进行修改呢?

const int global_const_vol = 10; 
char *s = "abcde";
int main()
{
        int *pointer = &global_const_vol;
           
        *pointer = 100;

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

 

 编译只有warning,和局部的const变量一样

 但执行就报段错误了,因为我们修改的是rodata段的变量。

结论:全局const变量是存放于rodata区的,无论如何都不能修改。

总结 

在gcc工具链中,局部const变量不能直接修改是由编译器控制的,其本身存放于代码运行时,临时分配的函数栈中。

而全局的const变量存放于rodata分区,任何时候都是只读变量。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值