从头学C(14)常量

0

常数是固定不变的数值,常量是程序运行时不会被修改的量。看似挺简单的一个概念,实际上还是要非常小心的。

之前我们已经接触了诸如整数常量、浮点数常量、符号常量、字符常量等等,有些不清不楚的地方,我们还需要好好整理下。

第二章 类型、运算符与表达式 >> 2.3 常量

先从整数常量说起:

  • 一般数值不太大的整数常量,如1234,属于int类型,计算时也会被当成整型来处理
  • 如果一个整数太大,超过了一个int类型所能表示的最大值,则会被当成long类型来处理
  • 通过以字母“l”或“L”结尾,来显示表明一个整数为long类型,比如1234L,5678l
  • 无符号常量以字母“u”或“U”结尾,如123u,456U
  • 以“ul”或“UL”为后缀的整数常量,则会被当成unsigned long型来处理

我们前面看到的都是以十进制表示的整型数,其实整型数还可以以八进制(用的不多)和十六进制(表示地址、寄存器的时候用得比较多)的形式表示:

  • 以数字0开头的整型常量表示它为八进制
  • 以0x或0X开头的整型常量表示它为十六进制

例如十进制数(31),表示为八进制是(037),表示为十六进制是(0x1f)。

想起当初网上一个很流行的关于程序员的段子,说:“为什么程序猿总是分不清“万圣节和圣诞节?” 那是因为“Oct 31 = Dec 25”(八进制的31等于十进制的25)。

注意:八进制和十六进制的常量也可以用后缀L表示long类型,用后缀U表示unsigned类型。比如0xFUL就是一个unsigned long(无符号长整型)类型的常量。

再说浮点数常量

  • 包含一个小数点(如123.4)或一个指数(如1e-2)的常量是浮点数常量,或者两者都有(如123.4e-2)
  • 没有任何后缀的浮点数常量是double类型
  • 后缀为f或F表明为float类型
  • 后缀为l或L表明为long double类型

关于字符常量

单引号括起来的单个字符,就是一个字符常量,也是一个整数,它的数值就是这个字符在机器字符集(通常是ASCII码表)中的数值。比如字符’0’代表数值48,而与数值0没有任何关系。

使用字符常量的好处是:程序员无需关心这个字符在机器字符集中代表的具体数值,可以写出易读的代码。所以字符常量一般是用于和其他字符进行比较,虽然它完全可以像整数一样参与计算。

某些字符(特别是非打印字符)可以通过转义字符序列表示为字符和字符串常量,比如’\n’、’\t’等等。虽然看起来像两个字符,但它实际上只表示一个字符。ANSI C语言中的全部转义字符序列如下所示:

\a 响铃符           \\   反斜杠
\b 回退符           \?   问号
\f 换页符           \'   单引号
\n 换行符           \"   双引号
\r 回车符           \000 八进制数
\t 横向制表符       \xhh 十六进制数
\v 纵向制表符

其中 ‘\000’和’\xhh’分别是八进制和十六进制形式的字符常量,000代表1-3个八进制数字(0~7),hh代表一个或两个十六进制数字,以下

#define VTAB '\013'    /* ASCII纵向制表符 */
#define BELL '\007'    /* ASCII响铃符 */

#define VTAB '\xb'    /* ASCII纵向制表符 */
#define BELL '\x7'    /* ASCII响铃符 */

是等价的。

另外,字符常量’\0’表示值为0的字符,也是空字符(null),通常用它代替数字0来强调某些表示表达式的字符属性。

关于常量表达式(只包含常量的表达式)必须要知道的是:它是在编译时求值,而不是在程序运行时才求值

字符串常量

字符串常量是用双引号括起来的0个或多个字符组成的序列,比如“This is a string”或“”(空字符串)。有几点要注意:

  1. 双引号并不是字符串的一部分,它只是起限定字符串的作用
  2. 转义字符序列在字符串中依然适用,比如在字符串中\”就表示双引号字符
  3. 编译时可以叫多个字符串常量连接起来,所以”hello,” ” world”等价于”hello, word”

从本质上看,字符串常量就是字符数组。字符串内部使用一个空字符’\0’作为串的结尾,因此,存放字符串的物理存储单元需要比字符串双引号中的字符数多一个单元来存放串的结束符’\0’。

字符常量与字符串常量的区别

字符常量用的是单引号,而字符串用的是双引号。拿’x’和”x”来举例:

  • 字符常量 ‘x’     :是一个整数,代表字符x在机器字符集中对应的整数值
  • 字符串常量”x”:是包含一个字符’x’以及一个结束符’\0’的字符数组

枚举常量

枚举是一个常量整型值的列表。例如:

enum boolean { No, Yes };

在没有显式说明的情况下,enum类型中第一个枚举名的值为0,第二个的值为1……以此类推。

也可以显式的指定所有枚举名的值,比如:

enum escapes { BELL = '\a', BACKSPACE = '\b', TAB = '\t'};

如果只指定了部分枚举名的值,那么未指定值的枚举名将依着最后一个指定值向后递增,如:

enum months { JAN = 1,FEB, MAR, APR, MAY, JUN,
              JUL, AUG, SEP, OCt, NOV, DEC };
             /* FEB值为2, MAR值为3 …… 以此类推 */

注意:不同枚举中的名字必须不能相同(有点类似符号常量,不能定义名字相同的符号常量),但是同一枚举中不同的名字可以具有相同的值。

枚举的好处在于:建立了常量值与名字之间的联系,调试时也可以直接打印出枚举变量的值,而且和#define相比,优势在于常量值可以自动生成。

Leave A Reply