对于c++中“常量折叠”的几点疑问(没有帖子问过的问题)

greatm 2007-10-16 01:56:38
c++里的常量折叠(或者常量替换)是将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。
下面是一个cpp文件:
#include 。。。。
const int i =1;
int main()
{
const int j = 2;
printf("%d,%d",i,j);
return 1;
}

那么:
(1)符号表本身是存在哪里的?是数据段里吧?
(2)我要强行取这个变量的地址的时候,比如:
const int *pi = &i;
const int * pj = &j;
这时i和j应该都会被分配内存吧?
那么i分配的内存是在数据段,J被分配的内存是在栈中,这对吗?
(3)我就知道c语言的const常量是要分配内存的。如果在c语言中同样有上面这么一段程序,那么i,j分别在哪里分配内存?

(4)c语言有“常量折叠”这样的优化吗?

(5)如果有,进行常量折叠优化时,这个const常量的值是放在寄存器中,每次都从寄存器中取其值?
还是跟c++一样,将其放在符号表中,编译器在编译时进行“替换”优化?
...全文
569 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
yzx714 2010-08-17
  • 打赏
  • 举报
回复
(1)符号表本身是存在哪里的?是数据段里吧?
(2)我要强行取这个变量的地址的时候,比如:
const int *pi = &i;
const int * pj = &j;
这时i和j应该都会被分配内存吧?
那么i分配的内存是在数据段,J被分配的内存是在栈中,这对吗?
(3)我就知道c语言的const常量是要分配内存的。如果在c语言中同样有上面这么一段程序,那么i,j分别在哪里分配内存?

(4)c语言有“常量折叠”这样的优化吗?

(5)如果有,进行常量折叠优化时,这个const常量的值是放在寄存器中,每次都从寄存器中取其值?
还是跟c++一样,将其放在符号表中,编译器在编译时进行“替换”优化?

1.这个符号表和常量折叠的符号表不是一回事儿,编译后,常量折叠的符号表就不存在了
2.对
3.同样
4.有
5.和C++一样
hastings 2010-08-17
  • 打赏
  • 举报
回复
??????????????这都行?
huayiluo 2010-08-17
  • 打赏
  • 举报
回复
07年的贴子。顶一下
星光伴月 2007-10-17
  • 打赏
  • 举报
回复
#include  <iostream > 
using namespace std;

int main(void)
{
const int a=10;
int * p = (int*)&a;//为了能尝试通过*p修改常量a的值,用了强制转换

cout < <"a = " < < a < <endl; //输出 a = 10
cout < <"*p= " < <*p < <endl; //输出 *p = 10
*p=100; //试图修改a的值
cout < <"a = " < < a < <endl; //仍然输出: a = 10
cout < <"*p= " < <*p < <endl; //这里却输出: *p = 100

system("pause");
}


以下是 cout < <"a = " < < a < <endl;
这一句在DEBUG时的汇编代码:
004114DB mov esi,esp
004114DD mov eax,dword ptr [__imp_std::endl (41A344h)]
004114E2 push eax
004114E3 mov edi,esp
004114E5 push 0Ah ;;;;;;;注意这里是个10,是个立即数
004114E7 push offset string "*p=" (417704h)
004114EC mov ecx,dword ptr [__imp_std::cout (41A348h)]
004114F2 push ecx
004114F3 call std::operator < < <std::char_traits <char > > (411159h)
004114F8 add esp,8
004114FB mov ecx,eax
004114FD call dword ptr [__imp_std::basic_ostream <char,std::char_traits <char > >::operator < < (41A34Ch)]
00411503 cmp edi,esp
00411505 call @ILT+410(__RTC_CheckEsp) (41119Fh)
0041150A mov ecx,eax
0041150C call dword ptr [__imp_std::basic_ostream <char,std::char_traits <char > >::operator < < (41A32Ch)]
00411512 cmp esi,esp
00411514 call @ILT+410(__RTC_CheckEsp) (41119Fh)
linking3000 2007-10-16
  • 打赏
  • 举报
回复
恩,了解了,学习一下
星光伴月 2007-10-16
  • 打赏
  • 举报
回复
虽然编译器为常量分配了地址,但是在使用常量的时,常量并不是存储在为它分配的地址上的,而是一个立即数,请看下面的例子:

#include <iostream>
using namespace std;

int main(void)
{
const int a=10;
int * p = (int*)&a;//为了能尝试通过*p修改常量a的值,用了强制转换

cout<<"a = "<< a<<endl; //输出 a = 10
cout<<"*p= "<<*p<<endl; //输出 *p = 10
*p=100; //试图修改a的值
cout<<"a = "<< a<<endl; //仍然输出: a = 10
cout<<"*p= "<<*p<<endl; //这里却输出: *p = 100

system("pause");
}


以下是 cout<<"a = "<< a<<endl;
这一句在DEBUG时的汇编代码:
004114DB mov esi,esp
004114DD mov eax,dword ptr [__imp_std::endl (41A344h)]
004114E2 push eax
004114E3 mov edi,esp
004114E5 push 0Ah ;;;;;;;注意这里是个10,是个立即数
004114E7 push offset string "*p=" (417704h)
004114EC mov ecx,dword ptr [__imp_std::cout (41A348h)]
004114F2 push ecx
004114F3 call std::operator<<<std::char_traits<char> > (411159h)
004114F8 add esp,8
004114FB mov ecx,eax
004114FD call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (41A34Ch)]
00411503 cmp edi,esp
00411505 call @ILT+410(__RTC_CheckEsp) (41119Fh)
0041150A mov ecx,eax
0041150C call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (41A32Ch)]
00411512 cmp esi,esp
00411514 call @ILT+410(__RTC_CheckEsp) (41119Fh)
linking3000 2007-10-16
  • 打赏
  • 举报
回复
1)这种变量放在全局变量区
2)会分配地址 pi,pj在全局变量区还是栈,要看他们在那里定义
3)4) c语言的不清楚
5)常量折叠优化?我不清楚这个概念,全局变量i或者j在编译的时候就可以直接将他们的地址传给用的地方
寄存器一般用于需要优化程序速度的时候,可以直接来赋值,不需要通过赋值给某个内存地址对应的空间
晨星 2007-10-16
  • 打赏
  • 举报
回复
(1)运行时的“符号表”跟编译时的“符号表”不完全是一回事;常量被折叠后,不“存在”于任何段中,只是作为立即数了。比如:
const int M = 5;
int i = M;
常量被折叠后,就跟int i = 5;没有任何区别。
常量如果分配内存,应该是在常量区。大多数运行时环境中,常量区跟栈不是一个区。

(2)强行取常量地址确实会导致内存分配。事实上,即使不取地址,内存也不一定不分配,这跟编译器的优化策略有关。换句话说,是不是“常量折叠后,只要不取地址,就一定不分配内存?”,语言标准当然没有明确规定,一切由编译器作者自己看着办。别忘了,C++语言中,常量是左值,所以即使统统分配内存,也没啥不好。最后,分配内存跟常量折叠本身不矛盾,这完全是两回事,即有内存分配并不表明不能被折叠,“折叠”说的是常量被使用的地方,而内存分配说的是变量被定义的地方。

(3)应该是在常量区。

(4)优化无极限,C语言编译器当然可以有这样的优化,甚至可以提供编译选项控制这样的优化。

(5)你说的“每次从寄存器中取值”,这个指的是数据存取指令的优化,而“放在符号表中,编译器在编译时进行替换”指的是程序转换优化。这两种优化不在一个抽像层次上,常量折叠指的是后者。

65,184

社区成员

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

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