c中的常量

来源:互联网 发布:搬家软件哪个好 编辑:程序博客网 时间:2024/05/13 23:37

前两天和冬哥讨论100这样的常量能不能取地址,当时我认为可以,后来查了一些资料,整理成这篇文章,总结关于c语言中关于常量的存储及表示的内容。

有三种常量,存储各有不同特点:1、类似于汇编中的立即数的常量;2、不能更改的带const修饰符的量;3、字符串常量

一、立即数

        这种类型可能有不同的处理方法,较为简单的数可能直接放到指令中去,复杂一点的数就放在静态数据区里。以下是一本教材的一段话,我找到的关于这个内容的资料只有这么一段《编译原理及实践教程》 P168,黄贤英,清华大学出版社:

        “在组织全局/静态数据区时,出现的一个问题是它设计编译时已知的一些常量,包括C和Pascal中用const声明及代码本身所用的文字值,例如C语句printf(“hello%d\n”,12345)中的字符窜“hello%d\n”和整型值12345,对于较小的在编译时的已知常量(如0或1),通常由编译程序直接插入到代码中(本人注:应该写作指令),不为其分配任何数据空间;对于大型的整型值、浮点值,特别是字符串就必须将其分配到存储器的全局/静态数据区中。(在C中字符串被看做指针,因此必须按这种方式保存)。

         应该说这段话有些细节上表述不妥,但对我们这里关心的问题,交代的比较明确:有的直接写进指令,有的存在静态数据区,字符串常量全在静态数据区。

         另外值得一提的是,即使一个复杂的浮点数,如3333.2345L,这几乎是最大的类型了,按上述说法,应该存在于静态数据存储区,但它仍然是不能取地址的——那么做也没有什么意义,如果打算在程序里修改它,直接定义成变量就行了。

二、const常量

        其实应该叫做const变量,《c primer plus》、《c 和指针》都这么叫,但是说const常量也不会误解。

        显然,如下例,const变量是分配了内存的,可以取地址的,可以通过其他方式来改变其值的,所谓的const不同于一般变量的地方就是不能通过其标号修改,其他没啥不同。如下是我的依据,vc2010:

             int _tmain(int argc, _TCHAR* argv[])
             {
                      float const pi=3.14f;
                      float *a=(float *)π
                      printf("at first,pi=%f\n",pi);
                      *a=6.24;
                      printf("then it become%f\n",pi);
                      return 0;
              }

          用const来代替宏定义有一个好处:节省空间,如

           #define pi 3.14

           float a=pi;

           float b=pi;

           这是,经过预处理,程序变成:

           float a=3.14;

           float b=3.14;

           这是程序如果优化得不好,就会在静态数据区出现两个3.14,分别用来给a、b赋值。若将宏定义改为float const pi=3.14,不但能在赋值时类型检查,还能节省存储空间,因为在给a、b赋值之前只有一个地方存储了3.14,那就是pi的存储单元。

           

        网上关于const常量有一些说法,下边两个流传很广,但是不对。

        这种常量是存在内存中的,和变量的唯一区别就是不能更改其值。但是又有人说(http://blog.csdn.net/lixiang100824/article/details/7473890),定义了const常量并初始化后,再通过其他的指针修改其存储单元的值,然后再用常量标号,其值并没有改变——这不知是c语言的标准还是某些编译器的做法。

         C++的编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作。http://blog.csdn.net/sptoor/article/details/6578893

         我认为,这两种说法基本都不对。第二个帖子流传很广,被大量转载。提符号表是多此一举,在编译的时候,建立符号表示当然的,const变量当然不例外,但是没有理由说编译器就把const当成了宏一样的东西直接替代。

三、字符串常量

        字符串常量是存储在内存中的静态存储区的,所以可以对一个字符串常量取地址,如&“i love you”

四、常量的表示

进制

        默认十进制,0开头表示八进制,0x开头表示十六进制

整形

        编译器通过写法来识别其类型,如果int足以表示,就默认为int型,不行就是long int,还不行就只好unsigned long,乃至long long甚至unsigned long long。

        也可以通过后缀告诉编译器用什么类型来存储,L或者l后缀表示long,LL或者ll是long long,u或者U是unsigned的意思

浮点型

         没有后缀就是double型,可以使用f或者F后缀变成float型,l或者L后缀变成long double型。

字符型

         转义序列\n等

         \07和\7一样,都是通过八进制表示字符(7前没有0仍然会理解为8进制)

         \ x7,这个事16进制表示ASCII码

原创粉丝点击