Posts Tagged ‘符号表’
Dec
编译器如何处理基本类型的const常量
by huubby in C and CPP
前段时间看《高质量C++&C编程指南》,看到一段比较有意思的代码,见下面这一坨:
const long lng = 100;
long * pLng = (long *)&lng;
*pLng = 20;
cout<<*pLng<<endl;
cout<<lng<<endl;
乍一看,嗯,确实有点问题,第二句long * pLng = (long *)&lng;消除了lng的常量性,这样指针就可以绕过编译器的检查而直接修改const常量的值。我自信满满的认为,输出结果肯定是20,20。继续往下看,这本破书竟然告诉我,输出的是20,100。当时我就“震精”了,立刻怀疑自己买的是某小印刷厂出的盗版书,又或者林锐这家伙脑子进水,乱写瞎忽悠。
我是个不信邪的人,马上拿小抄抄下来,第二天到电脑上一跑,输出的竟然真的是20,100。好消息是,我买的不是盗版书,大牛林锐也没脑子进水,乱写瞎忽悠。那就继续翻书找答案,原来人林锐早说了,“编译器把基本类型的const常量放入符号表中”。取该基本类型常量的地址,如long * pLng = (long *)&lng;时,编译器在内存中创建了一个该值的内存拷贝,然后把这个拷贝的地址返回给了pLng指针,以后修改指针指向的值时,修改的就是内存中拷贝的值,而不是原始的基本类型常量。代码加上注释后如下:
const long lng = 100; //基本类型常量,放入符号表中
long * pLng = (long *)&lng; //在内存中创建一个拷贝,并且返回该拷贝的地址给pLng
*pLng = 20; //修改的是内存中的拷贝的值
cout<<*pLng<<endl; //输出修改后的拷贝的值
cout<<lng<<endl; //符号表的值
下面还有坨代码:
class _MyClass
{
public:
_MyClass(int var):m_var(var){}
public:
int m_var;
};
const _MyClass myCls(23);
_MyClass* pMyCls = (_MyClass*)&myCls;
pMyCls->m_var = 45;
cout<<myCls.m_var<<endl;
cout<<pMyCls->m_var<<endl;
这个时候,输出的就是45,45啦。用户自定义类型的常量会分配内存空间,而不是放入符号表。
请注意:编译器只是将基本类型的const常量放入符号表中,其他用户自定义类型,非基本类型const常量,编译器会为其分配内存空间,而在编译时进行只读性检查。
2009年12月8日星期二