3.3 常量与变量
3.3.1 常量
C语言中的常量是指不接受程序修改的固定值。常量可为任意数据类型。
整型常量:21、123、2100、-234
浮点型常量:123.23、4.34e-3
字符常量:'a'、'\n'、'9'
下面具体介绍不同数据类型的常量。
1.整型常量
整型常量可分别以十进制、八进制、十六进制表示。C语言的整型常量有以下四种形式:
(1)十进制整数
形式:±n
其中,n是数字0~9组成的序列,中间不允许出现逗号,规定最高位不能是0。当符号为正时,可以省略符号“+”“-”表示负数。
例如,123、-1000、-1都表示十进制整数。
1.234、10-2、10/3、0123则为非法的十进制整数。
(2)八进制整数
形式:±0n
其中,0表示八进制数的引导符,不能省略;n是数字0~7组成的序列。当符号为正时,可以省略“+”“-”表示负数。特别要注意的是,八进制整数的引导符是数字0,而不是字母O。
例如,0123、01000、01都是表示八进制整数。
012889、123、670则为非法的八进制整数。
(3)十六进制整数
形式:±0xn
其中,0x表示十六进制数的引导符,不能省略。十六进制整数的引导符是数字0而不是字母O;n是0~9、a~f或A~F的数字、字母序列。当符号为正时,可以省略“+”
“-”表示负数。一般来讲,如果前面的字母x小写,则后面的a~f也应小写;如果前面的字母X大写,则后面的A~F也应大写。a~f或A~F分别表示数字10~15。
例如,0x12c、0x100、0XFFFF都是表示十六进制整数。
(4)长整型整数
前面几种表示形式的整型是基本整型,但对于超过基本整型取值范围的整数,可以通过在数字后加字母L或l来表示长整型整数。从表3-2可以看到,长整型整数的表示范围比基本整型大得多。
例如,123456L、07531246L、0XFFFFFFL分别表示十进制长整型整数、八进制长整型整数、十六进制长整型整数。
2. 浮点型常量
浮点型常量又称为实型常量,是一个用十进制表示的符号实数。符号实数的值包括整数部分、尾数部分和指数部分。浮点型常量的形式如下:
[digits][.digits][E|e[+|-]digits]
其中,digits是一位或多位十进制数字(0~9)。E(也可用e)是指数符号。小数点之前是整数部分,小数点之后是尾数部分,它们是可省略的。小数点在没有尾数时可省略。指数部分用E或e开头,幂指数可以为负,当没有符号时视为正指数,其基数为10,例如,1.575E10表示为1.575×1010。
在浮点型常量中,不得出现任何空白符号。在不加说明的情况下,浮点型常量为正值。如果表示负值,需要在常量前使用负号。下面是一些浮点型常量的示例:
15.75、1.575E10、1575e-2、-0.0025、-2.5e-3、25E-4
所有浮点型常量均视为双精度类型。实型常量的整数部分若为0,则0可以省略,如下形式是允许的:
.57、.0075e2、-.125、-.175E-2
注意:字母E或e之前必须有数字,且E或e后面指数必须为整数。
e3、2.1e3.5、.e3、e等都是不合法的指数形式。
3. 字符常量
字符常量是指用一对单引号括起来的单个字符,如'a'、'9'、'!'。字符常量中的单引号只起定界作用,并不表示字符本身。单引号中的字符不能是单引号(')和反斜杠(\),它们有特定的表示方法,这将在转义字符中介绍。
在C语言中,字符是按其所对应的ASCII码值来存储的,一个字符占一个字节。例如,部分字符的ASCII码值如下:
!: 33
0: 48
1: 49
9: 57
A: 65
B: 66
a: 97
b: 98
注意:字符‘9’和数字9的区别,前者是字符常量,后者是整型常量,它们的含义和在计算机中的存储方式截然不同。
由于C语言中的字符常量是按短整数(short型)存储的,因此字符常量可以像整数一样在程序中参与相关的运算。例如,
'a' - 32; / 执行结果97-32=65 /
'A' + 32; / 执行结果65+32=97 /
'9' – '0'; / 执行结果57-48=9 /
4. 字符串常量
字符串常量是指用一对双引号括起来的一串字符。双引号只起定界作用,双引号括起的字符串中不能是双引号(")和反斜杠(\),它们有特定的表示方法,这将在转义字符中介绍。例如,"China"、"C program"、"YES&NO"、"33312-2341"等。
在C语言中,字符串常量在内存中存储时,系统自动在字符串的末尾加一个“串结束标志”,即ASCII码值为0的字符'\0'。因此在程序中,长度为n个字符的字符串常量,在内存中占有n + 1个字节的存储空间。例如,字符串"China"有5个字符,作为字符串常量存储于内存中时,共占6个字节,系统自动在末尾加上'\0'字符,其存储形式为:
要特别注意字符常量与字符串常量的区别,除了表示形式不同外,其存储性质也不相同,字符常量'A'只占1个字节,而字符串常量"A"占2个字节。
5. 转义字符
转义字符是C语言中表示字符的一种特殊形式。通常使用转义字符来表示ASCII码字符集中不可打印的控制字符和特定功能的字符,如用于表示字符常量的单引号(')、用于表示字符串常量的双撇号(")、反斜杠(\)等。转义字符以反斜杠(\)开始,后面跟一个字符或一个八进制或十六进制数表示。表3-3给出了C语言中常用的转义字符。
字符常量中使用单引号和反斜杠以及字符串常量中使用双引号和反斜杠时,都必须使用转义字符表示,即在这些字符前加上反斜杠。在C程序中使用转义字符\o[o[o]]或\xh[h]可以方便灵活地表示任意字符。\o[o[o]]为反斜杠(\)和随后的1~3位八进制数字构成的字符序列。例如,'\60'、'\101'、'\141'分别表示字符'0'、'A'和'a',因为字符'0'、'A'和'a'的ASCII码的八进制值分别为60、101和141。\xh[h]为反斜杠(\)和字母x
(或X)及随后的1~2个十六进制数字构成的字符序列。例如,'\x30'、'\x41'、'\X61'分别表示字符'0'、'A'和'a',因为字符'0'、'A'和'a'的ASCII码的十六进制值分别为0x30、0x41和0x61。使用转义字符时需要注意以下几点:
1)转义字符中只能使用小写字母,每个转义字符只能看作一个字符。
2)\v垂直制表符和\f换页符对屏幕没有任何影响,但会影响打印机执行相应操作。
3)在C程序中,使用不可打印字符时,通常用转义字符表示。
4)'\n'应该叫回车换行。回车只是回到行首,不改变光标的纵坐标;换行只是换一行,不改变光标的横坐标。
5)转义字符'\0'表示空字符NULL,它的值是0。而字符'0'的ASCII码值是48,因此空字符'\0'不是字符0。另外,空字符不等于空格字符,空格字符的ASCII码值为32而不是0。编写程序时,读者应当区别清楚。
6)如果反斜杠之后的字符和它不构成转义字符,则反斜杠不起转义作用,按正常普通字符处理。
6. 符号常量
C语言允许将程序中的常量定义为一个标识符,称为符号常量。符号常量一般使用大写英文字母表示,以区别于一般用小写字母表示的变量。符号常量在使用前必须先定义,其定义形式为:#define <符号常量名> <常量>
例如,
#define PI 3.1415926
#define TRUE 1
#define FALSE 0
#define STAR '*'
这里定义PI、TRUE、FALSE、STAR为符号常量,其值分别为3.1415926、1、0、'*'。#define
是C语言的编译预处理指令,它表示经定义的符号常量在程序运行前将由其对应的常量替换。定义符号常量的目的是为了提高程序的可读性,便于程序的调试和修改,因此在定义符号常量名时,应使其尽可能地表达它所表示的常量的含义,例如前面所定义的符号常量名PI(π),表示圆周率3.1415926。此外,若要对一个程序中多次使用的符号常量的值进行修改,只需对预处理指令中定义的常量值进行修改即可。
3.3.2 变量
其值可以改变的量称为变量。一个变量应该有一个名字(标识符),在内存中占据一定的存储单元,在该存储单元中存放变量的值。请注意区分变量名和变量值这两个不同的概念。
所有C语言中的变量必须在使用之前先定义。定义变量的一般形式为:
type variable_list;
这里的type必须是有效的C数据类型,variable_list(变量表)可以由一个或多个由逗号分隔的多个标识符构成。下面给出一些定义的范例。
int i, j, l;
short int si;
unsigned int ui;
double balance, profit, loss;
程序员应根据变量的取值范围和含义,选择合理的数据类型。下面详细介绍整型变量、浮点型(实型)变量及字符型变量。
1.整型变量
C语言规定在程序中所有用到的变量都必须在程序中指定其类型,即“定义”。例如,
#include <stdio.h>
int main()
{
int a,b,c,d; / 定义a, b, c, d为整型变量 /
unsigned int u; / 定义u为无符号整型变量 /
a = 22; b = -11; u = 5;
c = a + u; d = b + u;
printf("a+u=%d, b+u=%d\n", c, d);
}
运行结果为:
a+u=27,b+u=-6
可以看到,不同类型的整型数据可以进行算术运算。在本例中是int型数据与unsigned int型数据进行加减运算。
2. 浮点型变量
浮点型变量分为单精度型(float型)和双精度型(double型)。每一个浮点型变量都应该在使用前加以定义,例如,
float x, y; / 定义x, y为单精度浮点数 /
double z; / 定义z为双精度浮点数 /
在一般系统中,一个float型数据在内存中占4个字节(32位),一个double型数据占8个字节(64位)。单精度浮点数提供7~8位有效数字,双精度浮点数提供15~16位有效数字,数值的范围随机器系统而异。值得注意的是,浮点型常量是double型,当把一个浮点型常量赋给一个float型变量时,系统会截取相应的有效位数。例如,
float a;
a = 111111.111;
由于float型变量只能提供7~8位有效数字,因此可能损失精度。如果将a改为double型,则能全部接收上述9位数字并将其存储在变量a中。
3. 字符变量
字符变量用来存放字符数据。注意:只能存放一个字符,不要以为在一个字符变量中可以存放字符串。字符变量的定义形式为:char c1, c2;
它表示c1和c2为字符变量,各存放一个字符。因此可以用下面语句对c1、c2赋值:c1 = 'a'; c2 = 'b';
又如,
#include <stdio.h>
int main( )
{
char c1, c2; / 定义c1、c2为字符变量 /
c1 = 97; c2 = 98; / 对字符变量c1、c2赋值 /
printf("%c,%c", c1, c2); / 输出c1、c2 /
return 0;
}
其中,c1、c2被定义为字符变量。但在第3行中,将整数97和98分别赋给c1和c2,它的作用相当于以下两个赋值语句:c1 = 'a'; c2 = 'b';
因为字符'a'和'b'的ASCII码分别为97和98。第4行将输出两个字符,"%c"是输出字符的格式控制,最终的程序输出为:a,b
又如,
#include <stdio.h>
int main ()
{
char c1, c2;
c1 = 'a'; c2 = 'b';
c1 = c1 – 32; / 将字符变量c1转换为大写字母 /
c2 = c2 – 32; / 将字符变量c2转换为大写字母 /
printf ("%c,%c",c1, c2);
return 0;
}
运行结果为:A,B
它的作用是将两个小写字母转换为大写字母。因为'a'的ASCII码为97,而'A'为65,'b'为98,而'B'为66。从ASCII码表中可以看到,每一个小写字母比大写字母的ASCII码大32,即'a'值等于'A' + 32。读者仔细观察ASCII表后,可能会发现一个有趣的现象:大小写字母在ASCII表中是分别连续的。基于这个观察,上面的小写字母转换为大写字母的表达式可以变化为:c1=c1- ('a' - 'A')或c1=c1- ('b' - 'B'),以此类推,还能写出很多变通的表达式,而不需要记牢大小写字母在ASCII中的跨度常量32。同样也能观察到'0'~'9'在ASCII中也是连续的,因此'9'-'0'正好得到数字9本身。读者还能观察ASCII表中的一些其他有趣的现象,这些在以后的编程中可能会作为小技巧用到。
3.3.3 变量的初始化
变量的初始化是指在定义变量的同时给变量赋以初值,使某些变量在程序开始执行时就具有确定的值。
其形式为:
<数据类型> <变量标识符> = <常量表达式>;
例如,
char c = 'A', ky = 'K'; / 字符变量c、ky初值分别为'A'、'K' /
int j, i = 1; / 整型变量i初值为1, j没有赋初值 /
float sum = 3.56; / 单精度变量sum 初值为3.56 /
如果对几个变量赋以相同的初值,不能写成:int a = b = c = 3;
而应写成:int a = 3, b = 3, c = 3;
赋初值相当于一个赋值语句。例如,int a = 3;
相当于:int a; / 定义a为整型变量 /
a = 3; / 赋值语句,将3赋给a /
又如,int a = 4, b, c = 5;
相当于:
int a, b, c;
a = 4;
c = 5;
对变量所赋初值,可以是常量,也可以是常量表达式。例如,double alf = 3.14159 / 180;