关于const常量的存储位置

patricxuqi 2010-06-01 10:30:17
网上有说const常量存储于符号表里。于是做了下实验,但是实验结果好像并不完全是。个人认为应该这样说:符号表里存放的内容包括类中的静态常量和全局变量。不知这个断言对吗?以下是实验代码和结果。大家有什么看法?欢迎拍砖。
#include <iostream>
using namespace std;

const int i = 100;
int n = 0;

class CTest
{
public:
CTest():j(0),l(0){};
int l;
const int j;//静态成员变量必须由默认构造函数初始化
static const int k = 102;
};

void main()
{
CTest ct ;
int m = 0;
const int o = 0;

long addri = (long)&i;
long addrl = (long)&ct.l;
long addrj = (long)&ct.j;
long addrk = (long)&ct.k;
long addrm = (long)&m;
long addrn = (long)&n;
long addro = (long)&o;

cout<<"addr i="<<addri<<endl; //addr i=4290560(符号表)
cout<<"addr l="<<addrl<<endl; //addr l=1310556
cout<<"addr j="<<addrj<<endl; //addr j=1310560
cout<<"addr k="<<addrk<<endl; //addr k=4290564(符号表)
cout<<"addr m="<<addrm<<endl; //addr m=1310544
cout<<"addr n="<<addrn<<endl; //addr n=4297032(符号表)
cout<<"addr o="<<addro<<endl; //addr o=1310532
getchar();
}
...全文
4923 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
nazzon2004 2010-09-08
  • 打赏
  • 举报
回复
常量的地址。
const 初始化多少 就是那个整形数的地址
leavestarshining 2010-09-07
  • 打赏
  • 举报
回复
c++里的常量折叠(或者常量替换)是将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。
开始理解了...
tian_jut 2010-07-06
  • 打赏
  • 举报
回复
另外建议参看此文
你的变量究竟存储在什么地方 && 全局内存
tian_jut 2010-07-06
  • 打赏
  • 举报
回复 1
const全局变量存放在.rodata只读数据段里,修改会造成SEGV
const局部变量存放在栈上,和普通局部变量无差别,可以用指针间接修改const值。

理由:
在linux上验证。
const int data = 1; //使用指针修改引起程序SEGV崩溃
main()
{
int *p = &data;
*p = 2;

}

编译完后使用objdump -t或者readelf -s命令,可以发现data被放在.rodata section

说放在符号表是不对的。
rabbitgoat 2010-06-02
  • 打赏
  • 举报
回复
我是来学习的,同意楼上的建议,常量折叠
CVA4508M 2010-06-02
  • 打赏
  • 举报
回复
google了下

呵呵,原来 "常量折叠"也就是来自C++的编程思想。。
我直接看英文版的,倒是第一次见这个名词。。

http://hi.baidu.com/american%CC%F0%B3%C8/blog/item/345d36507bc88a2d43a75b3e.html
CVA4508M 2010-06-02
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 cva4508m 的回复:]
引用楼主 patricxuqi 的回复:
网上有说const常量存储于符号表里。于是做了下实验,但是实验结果好像并不完全是。个人认为应该这样说:符号表里存放的内容包括类中的静态常量和全局变量。不知这个断言对吗?以下是实验代码和结果。大家有什么看法?欢迎拍砖。

C/C++ code
#include <iostream>
using namespace std;

const int……
[/Quote]

之前说了,符号表是编译器里的东西
实验的话,只能看编译器的源码了。。。。
本人就没研究过了,楼主有兴趣的话,可以翻翻编译器的源码,看看里面是否有这样的优化
CVA4508M 2010-06-02
  • 打赏
  • 举报
回复
C++编程思想真是一本非常好的书,最近在CSDN上看到好多问题
都可以在里面找到答案。
推荐大家都好好看看
CVA4508M 2010-06-02
  • 打赏
  • 举报
回复
[Quote=引用楼主 patricxuqi 的回复:]
网上有说const常量存储于符号表里。于是做了下实验,但是实验结果好像并不完全是。个人认为应该这样说:符号表里存放的内容包括类中的静态常量和全局变量。不知这个断言对吗?以下是实验代码和结果。大家有什么看法?欢迎拍砖。

C/C++ code
#include <iostream>
using namespace std;

const int i = 100;
int n = 0;
……
[/Quote]
const常量存储于符号表里,这是编译器的一个优化而已
现在的编译器很聪明的,当你没有对const变量进行&运算的时候,它就可能做这个优化

另外,发现楼主对符号表的理解错了,
符号表,仅仅是在编译器编译时,在编译器编译过程中编译器内部产生的一个临时的列表而已。
编译结束后就不再需要的。所以,它是不会占用程序的内存

cout<<"addr i="<<addri<<endl; //addr i=4290560(符号表)

这里的4290560不过是一个一般的内存地址而已
(由于楼主对const做了取值,所以聪明的编译器取消了这个优化)


引用《C++编程思想》中的一段

C++中的const默认为内部连接,也就是说,const仅在const被定义过的文件里才是可见的,而在连接时不能被其他编译单元看到。当定义一个const时,必须赋一个值给它,除非用extern作出了清楚的说明。
通常C++编译器并不为const创建存储空间,相反它把这个定义保存在它的符号表里。但是extern强制进行了存储空间分配(另外还有一些情况,如取一个const的地址,也要进行存储空间分配),由于extern意味着使用外部连接,因此必须分配存储空间,这也就是说有几个不同的编译单元应当能够引用它,所以它必须存储空间。





pengzhixi 2010-06-02
  • 打赏
  • 举报
回复
这就是所谓的常量折叠,你可以去google常量折叠,或许有解释得更清楚的。
pengzhixi 2010-06-02
  • 打赏
  • 举报
回复
const int i=10;//这个类似宏替换,也就是说,它优化之后可能是放一个符号表里面。所有使用i的地方都用10代替,但是当你对i取址后,没办法,编译器必须为i在常量区找个地方安身。
patricxuqi 2010-06-02
  • 打赏
  • 举报
回复
越来越困惑。期待高手用“实验”来证明!
CVA4508M 2010-06-02
  • 打赏
  • 举报
回复
建议楼主复习下编译原理吧。。。
CVA4508M 2010-06-02
  • 打赏
  • 举报
回复

另外,发现楼主对符号表的理解错了,
符号表,仅仅是在编译器编译时,在编译器编译过程中编译器内部产生的一个临时的列表而已。
编译结束后就不再需要的。所以,它是不会占用程序的内存


楼主仍然没理解符号表。。。
你说的那个能导出的符合表。。是目标文件中,用于连接的那个符号表,跟我们说的,编译器优化使用的符号表,是两个完全不同的东西。。。
patricxuqi 2010-06-02
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 cva4508m 的回复:]
引用楼主 patricxuqi 的回复:
网上有说const常量存储于符号表里。于是做了下实验,但是实验结果好像并不完全是。个人认为应该这样说:符号表里存放的内容包括类中的静态常量和全局变量。不知这个断言对吗?以下是实验代码和结果。大家有什么看法?欢迎拍砖。

C/C++ code
#include <iostream>
using namespace std;

const int……
[/Quote]
持保留意见
patricxuqi 2010-06-02
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 pengzhixi 的回复:]
你想看编译后的PE文件内容?
[/Quote]
是想知道。看看到底放了些什么东西在里面。linux下可以导出符号表里面的东西。但是不知道windows下面怎么弄。我另开一贴吧。
CVA4508M辛苦了。
CVA4508M 2010-06-02
  • 打赏
  • 举报
回复
$ uname -r
2.6.32-22-generic
$ g++ --version
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ cat main.cpp
#include <iostream>

using namespace std;

int main()
{
const int a = 1;
const int b = 2;
int sum = a + b;
cout << sum;
return 0;
}
$ g++ main.cpp -o test-release
$ g++ -O3 main.cpp -o test-o3

test-o3

public main
main proc near
push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 10h
mov dword ptr [esp+4], 3
mov dword ptr [esp], offset _ZSt4cout@@GLIBCXX_3_4
call __ZNSolsEi ; std::ostream::operator<<(int)
xor eax, eax
leave
retn
main endp



test-release

public main
main proc near
push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 20h
mov dword ptr [esp+1Ch], 1
mov dword ptr [esp+18h], 2
mov dword ptr [esp+14h], 3
mov eax, [esp+14h]
mov [esp+4], eax
mov dword ptr [esp], offset _ZSt4cout@@GLIBCXX_3_4
call __ZNSolsEi ; std::ostream::operator<<(int)
mov eax, 0
leave
retn
main endp


楼主自己看吧,不说了
赵4老师 2010-06-02
  • 打赏
  • 举报
回复
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!

无汇编无真相!
pengzhixi 2010-06-02
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 patricxuqi 的回复:]
在linux系统下,const存放在rdata里面。windows下怎么看数据段呢?
[/Quote]
你想看编译后的PE文件内容?
patricxuqi 2010-06-02
  • 打赏
  • 举报
回复
在linux系统下,const存放在rdata里面。windows下怎么看数据段呢?
加载更多回复(9)
内容概要:本文深入探讨了DMA高效数据传输实现方案在高性能计算芯片领域的应用与架构创新,重点分析了缓存一致性DMA、多通道DMA架构及其在数据中心SmartNIC、存算一体芯片和Chiplet互连等场景中的实践。文章结合RISC-V架构,通过Chisel硬件描述语言和C语言驱动代码,展示了多通道DMA控制器的设计与实现,涵盖仲裁机制、AXI总线适配、分散-聚集传输模式及中断处理等核心技术,并强调了性能优化与验证方法。最后展望了AI调度、光互连、近存计算与安全DMA等未来发展方向。; 适合人群:具备数字电路与计算机体系结构基础,从事芯片设计、嵌入式开发或高性能计算相关工作的研发人员,尤其是有1-5年经验的工程师与研究人员。; 使用场景及目标:①理解DMA在突破“内存墙”和降低系统能耗中的关键技术路径;②掌握多通道DMA控制器的硬件设计与驱动开发方法;③应用于SmartNIC、AI加速器、Chiplet等高性能芯片系统的数据传输架构设计;④为构建高带宽、低延迟、高能效的异构计算平台提供参考。; 阅读建议:此资源融合硬件设计与软件驱动,建议结合Chisel仿真与RISC-V平台实操,重点关注DMA与缓存一致性、异构计算单元的协同机制,并通过性能计数器与错误注入手段进行系统级验证。
内容概要:本文围绕基于共享储能服务的智能楼宇双层优化配置展开研究,通过Matlab代码实现相应的数学建模与仿真分析,提出一种结合上层规划与下层运行的协同优化框架,旨在提升智能楼宇能源系统的经济性、能效水平与电网互动能力。研究充分考虑光伏发电、负荷需求、储能充放电等多元因素,采用先进的优化算法(如智能优化算法)对共享储能资源的容量配置与运行调度进行精细化决策,有效降低用能成本,提高可再生能源消纳率,并增强系统运行的稳定性与灵活性。全文涵盖模型构建、算法设计、求解流程及结果验证,具备较高的理论深度与工程应用价值; 适合人群:具备电力系统、能源管理、优化算法等相关背景的科研人员、研究生,以及从事智能电网、综合能源系统、建筑节能等领域的工程技术人员; 使用场景及目标:①用于智能楼宇及园区级能源系统的规划与运行优化研究;②支撑共享储能机制下的资源配置、经济调度与商业模式设计;③作为Matlab仿真教学与高水平论文复现的典型案例,帮助深入理解双层优化模型、主从博弈结构及智能算法在能源系统中的应用; 阅读建议:建议结合提供的Matlab代码进行同步学习与调试,重点关注上下层模型的耦合关系与迭代求解过程,可进一步拓展至多主体协同、不确定性建模(如风光出力波动)及鲁棒优化等前沿方向开展深化研究。
内容概要:本文《【故障检测】基于 KPCA 的故障检测【T2 和 Q 统计指数的可视化】(Matlab代码实现)》系统阐述了基于核主成分分析(KPCA)的非线性故障检测方法,重点实现了T²和Q统计量的构建与可视化过程。通过Matlab编程,将高维非线性数据映射至特征空间,提取主成分并建立监控模型,利用T²和Q指数对工业过程中的异常状态进行联合监测与诊断,有效提升了复杂系统中早期故障的识别能力,具有较强的工程实用性与理论参考价值。; 适合人群:适用于具备信号处理、控制工程或工业过程监测背景,熟悉Matlab编程语言,并从事故障诊断、智能运维、自动化系统研发等相关工作的研究生、科研人员及工程技术开发者。; 使用场景及目标:①应用于化工、电力、制造等流程工业中的关键设备状态监控与早期故障预警;②作为学术研究中KPCA算法的仿真验证平台,用于对比分析不同非线性降维方法的检测性能;③深化对非线性过程监控中统计指标设计与阈值判定机制的理解与实践应用。; 阅读建议:建议读者结合所提供的Matlab代码逐模块运行与调试,深入掌握KPCA建模流程、主成分子空间划分及T²、Q统计量的计算逻辑,鼓励在标准数据集(如TE过程)上复现实验结果,并尝试扩展至其他非线性场景以提升模型泛化能力。

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧