The C Programming Language(第 2 版) 笔记 / 2 类型、运算符与表达式 / 2.3 常量

目录、参考文献


2.3 常量

类似于 1234 的整数常量属于 int 类型,long 类型的常量以字母 lL 结尾,如 123456789L
如果一个整数太大以至于无法用 int 类型表示时,也将被当作 long 类型处理
无符号常量以字母 uU 结尾
后缀 ulUL 表明是 unsigned long 类型

浮点数常量中包含一个小数点(如 123.4)或一个指数(如 1e-2),也可以两者都有
没有后缀的浮点数常量为 double 类型,后缀 fF 表示 float 类型,而后缀 lL 则表示 long double 类型

整型数除了用十进制表示外,还可以用八进制或十六进制表示
带前缀 0 的整型常量表示它为八进制形式;前缀为 0x0X,则表示它为十六进制形式
例如,十进制数 31 可以写成八进制形式 037,也可以写成十六进制形式 0x1f0X1F
八进制与十六进制的常量也可以使用后缀 L 表示 long 类型,使用后缀 U 表示 unsigned 类型
例如,0XFUL 是一个 unsigned long 类型(无符号长整型)的常量,其值等于十进制数 15

一个字符常量是一个整数,书写时将一个字符括在单引号中,如 'x'
字符在机器字符集中的数值就是字符常量的值
例如,在 ASCII 字符集中,字符 '0' 的值为 48,它与数值 0 没有关系
如果用字符 '0' 代替这个与具体字符集有关的值(比如 48),那么,程序就无需关心该字符对应的具体值,增加了程序的易读性
字符常量一般用来与其它字符进行比较,但也可以像其它整数一样参与数值运算

某些字符可以通过转义字符序列(例如,换行符 \n)表示为字符和字符串常量
转义字符序列看起来像两个字符,但只表示一个字符

另外,可以用 '\ooo' 表示任意的字节大小的位模式
其中,ooo 代表 1 ~ 3 个八进制数字(0…7)
这种位模式还可以用 '\xhh' 表示,其中,hh 是一个或多个十六进制数字(0…9,a…f,A…F)
因此,我们可以按照下列形式书写语句:

#define VTAB '\013' /* ASCII vertical tab */ 
#define BELL '\007' /* ASCII bell character */

上述语句也可以用十六进制的形式书写为:

#define VTAB '\xb' /* ASCII vertical tab */ 
#define BELL '\x7' /* ASCII bell character */

ANSI C 语言中的全部转义字符序列如下所示:

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

字符常量 '\0' 表示值为 0 的字符,也就是空字符(null)
通常用 '\0' 的形式代替 0,以强调某些表达式的字符属性,但其数字值为 0

常量表达式是仅仅只包含常量的表达式
这种表达式在编译时求值,而不在运行时求值
它可以出现在常量可以出现的任何位置,例如:

#define MAXLINE 1000 
char line[MAXLINE + 1];

#define LEAP 1 /* in leap years */ 
int days[31 + 28 + LEAP + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31];

字符串常量也叫字符串字面值,是用双引号括起来的 0 个或多个字符组成的字符序列
例如:

"I am a string"

"" /* 空字符串 */

双引号不是字符串的一部分,它只用于限定字符串
字符常量中使用的转义字符序列同样也可以用在字符串中
在字符串中使用 \" 表示双引号字符
编译时可以将多个字符串常量连接起来,如下列形式:

"hello," " world"

等价于

"hello, world"

字符串常量的连接为将较长的字符串分散在若干个源文件行中提供了支持

从技术角度看,字符串常量就是字符数组
字符串的内部表示使用一个空字符 '\0' 作为串的结尾
因此,存储字符串的物理存储单元数比括在双引号中的字符数多一个
这种表示方法也说明,C 语言对字符串的长度没有限制,但程序必须在扫描完整个字符串之后才能确定字符串的长度
标准库函数 strlen(s) 可以返回字符串参数 s 的长度,但长度不包括末尾的 '\0'
下面是我们设计的 strlen 函数的一个版本:

/* strlen: return length of s */ 
int strlen(char s[]) 
{ 
    int i; 
    while (s[i] != '\0') 
        ++i; 
    return i; 
}

标准头文件 <string.h> 中声明了 strlen 和其它字符串函数

我们应该搞清楚字符常量与仅包含一个字符的字符串之间的区别:'x'"x" 是不同的
前者是一个整数,其值是字母 x 在机器字符集中对应的数值(内部表示值)
后者是一个包含一个字符(即字母 x)以及一个结束符 '\0' 的字符数组

枚举常量是另外一种类型的常量
枚举是一个常量整型值的列表,如:

enum boolean { NO, YES };

在没有显式说明的情况下,enum 类型中第一个枚举名的值为 0,第二个为 1,依此类推
如果只指定了部分枚举名的值,那么未指定值的枚举名的值将依着最后一个指定值向后递增
参看下面两个例子中的第二个例子:

// 定义枚举类型 escapes
enum escapes { BELL = '\a', BACKSPACE = '\b', TAB = '\t', 
                NEWLINE = '\n', VTAB = '\v', RETURN = '\r' };
// 定义枚举类型 months
enum months { JAN = 1, FEB, MAR, APR, MAY, JUN, 
                JUL, AUG, SEP, OCT, NOV, DEC }; 
                        /* FEB 的值为 2,MAR 的值为 3,依此类推 */

enum months lastMonth; // 声明 enum months 类型的变量 lastMonth
enum
{
    saturday,
    sunday = 0,
    monday,
    tuesday,
    wednesday,
    thursday,
    friday
} workday; // 声明匿名枚举类型变量 workday
enum week { Mon = 1, Tue, Wed, Thu, Fri Sat, Sun } days; // 定义枚举类型 week,并声明 enum week 类型的变量 days

不同枚举中的名字必须互不相同,同一枚举中不同的名字可以具有相同的值

枚举为建立常量值与名字之间的关联提供了一种便利的方式
相对于 #define 语句来说,它的优势在于常量值可以自动生成
尽管可以声明 enum 类型的变量,但编译器不检查这种类型的变量中存储的值是否为该枚举的有效值
尽管如此,枚举变量提供了类型检查的机会(包含了可供检查的必要信息),因此通常比 #defines 更好
此外,调试程序可以以符号形式打印出枚举变量的值


目录、参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值