C教程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.3 内存和变量

在计算机内部,数据的存取操作都是通过所依附的连续多字节内存空间来进行的。但在程序中,如何来引用这些数据的内存空间呢?通过内存空间的首地址,是引用的一种方法。那么能否用一个标识符将其和一块内存空间绑定在一起呢?如果可以的话,该如何绑定呢?标识符又是如何命名的呢?

2.3.1 标识符

标识符(Identifiers)是独立的有效字符序列,是给程序中的一些程序元素(如变量、函数、数组等)所起的名字。在C语言中,一个合法的标识符应遵循下列规则:

(1)标识符由大小写英文字母、数字字符(0~9)和下画线组成,且第一个字符必须为字母或下画线,其后跟零个或多个字母、数字或下画线。例如,nLong, _, __(两个下画线),_123都是合法的标识符。但标识符中不能有空格、标点符号、运算符或其他字符,例如,下面的标识符就是不合法的:

(2)C语言中的大小写是敏感的。也就是说,大写字母与小写字母分别代表不同的标识符。例如,data,Data,DaTa,DATA等都是不同的标识符。尽管如此,也尽量不要将两个标识符定义成字母相同、大小写不同的标识符。

(3)不能与关键字同名。所谓关键字,是指由系统内部定义的,具有特殊含义和用途的标识符,程序中不能另做他用。以下是32个ANSI C关键字:

auto     break    case     char     const    continue
default   do      double   else      enum    extern
float     for      goto     if       int      long
register   return   short    signed   sizeof    static
struct    switch   typedef   union    unsigned  void
volatile   while

需要说明的是:程序中定义的标识符除了不能与关键字同名外,还应不与系统库文件中预定义的标识符或库函数同名,如以前遇到的printf,scanf等;最好也不要与关键字相似或只是大小写区别,如Int,Long等,虽然这在C语言中是合法的,但在有的C编译器中可能会将Int和Long看做是int和long的别名,可见它们都是不好的标识符。再如,include, define虽是合法的标识符,但它和预处理命令#include,#define相似,也是不好的。

除了遵循上述规则外,标识符命名时还应考虑以下两点。

(1)要考虑标识符的有效长度。即组成标识符的字符个数不要太多,一般不能超过32个,因为有的编译系统只能识别前32个字符,也就是说前32个字符相同的两个不同标识符会被某些系统认为是同一个标识符。

(2)要考虑标识符的易读性。例如,a1b1,c1d虽然是合法的标识符,但却是不好的标识符,因为它不能让人理解它们所代表的含义。在定义标识符时,若能做到“见名知义”就能达到提高易读性的目的。

2.3.2 变量和变量定义

有了标识符的规则,就可以为程序中的变量起一个名称。那么,什么是变量呢?变量是如何使用的呢?

1.变量的含义

变量,顾名思义,是指其值是可以改变的量。但在C语言中,变量的含义还不止这些。

前面已提及,程序中的数据是通过内存来操作的。但由于不同的编译系统为同一个数据所开辟的内存的地址不一定相同,因此为了方便编程人员使用,允许通过一个标识符来标识所使用的内存空间。这个标识符在程序中称为变量的名称。为了能精确地反映这个内存空间的大小,变量还必须要有数据类型,数据类型同时还反映这个内存空间存取的是怎样的数据以及数据值的范围。

可见,与数学中的变量概念有着本质的不同,程序中的变量是计算机内部的某块内存空间在程序中的标识。在程序中,使用变量就是使用该变量所绑定的内存空间。那么变量名和内存空间是如何绑定的呢?这就需要在程序中对变量进行定义。

2.变量的定义

C语言在定义变量时先写数据类型,然后是变量名,数据类型和变量名之间必须用一个或多个空格来分隔,最后以分号来结尾,即如下列格式的变量定义语句:

<数据类型> <变量名1>[ , <变量名2>, …];

凡格式中出现的尖括号“< >”,表示括号中的内容必须是指定的,若为方括号“[ ]”,则括号中的内容是可选的,本书做此约定

数据类型告诉编译器要为由变量名指定的变量分配多少字节的内存空间,以及变量中要存取的是什么类型的数据。例如:

double    x;                       /* 双精度实型变量 */

一旦编译,系统就会自动将x这个标识符和10字节(以ANSI C为准)的连续内存空间相绑定,直到x生存期结束为止。也可以说,上述定义编译后,系统就会为x变量根据其类型(double)开辟10字节的内存空间。或者说,x占用了10字节的连续内存空间,存取的数据类型是double型,称之为双精度实型变量。再如:

float y;                           /* 单精度实型变量 */

则y占用了4字节的连续内存空间,存取的数据类型是float型,称之为单精度实型变量。此后,变量x,y就分别对应于各自的内存空间,换句话说,开辟的那块8字节的内存空间就称为x,另一块4字节的内存空间就称为y。又如:

int  nNum1;                       /* 整型变量 */
int  nNum2;                       /* 整型变量 */
int  nNum3;                       /* 整型变量 */

则在ANSI C中,nNum1,nNum2,nNum3分别占用2字节的存储空间,其存取的数据类型是int型,称之为整型变量。由于它们都是同一类型的变量,因此为使代码简洁,可将同类型的变量定义在1行语句中。不过,同类型的变量名要用逗号“,”分隔(逗号前后可以有0个或多个空格)。例如,这3个整型变量可这样定义(注意:只有最后一个变量nNum3的后面才有分号):

int  nNum1,nNum2,nNum3;

需要说明:

(1)除了上述整型变量、实型变量外,还可有字符型变量,即用char定义的变量,这些都是基本数据类型变量。实际上,只要是合法的数据类型,均可以用来定义变量。例如:

unsigned short  x,  y,  z;             /* 无符号短整型变量 */
long double     pi;                    /* 长双精度实型变量 */

(2)变量是有作用范围的,称为变量的作用域(以后会讨论)。C语言规定:在同一个作用域中,不能有两个或以上相同的标识符(变量名)。例如:

float x,  y,  z;                     /* 单精度实型变量 */
int  x;                              /* 错误,变量x重复定义 */
float y;                             /* 错误,变量y重复定义 */

3.定义位置

在C语言中,对变量定义的位置还有下列一些规定。

(1)在由左花括号“{”和右花括号“}”构成的函数体或语句块中,变量定义语句必须出现在函数体或语句块中的最前面,且变量定义语句的前面不能存在其他非变量定义语句或非说明语句。例如:

int main()
{
    int   a;                       /* 合法 */
    int   x;                       /* 合法 */
    x=8;                         /* 赋值语句 */
    int   y;                       /* 不合法,前面出现非变量定义语句 */
    {
        int  c;                   /* 合法 */
        …
    }
    …
    return 0;
}

(2)可以在main函数外定义变量(称为全局变量,以后还会讨论),定义的位置虽没限定,但一定要遵循先定义后使用的原则。

2.3.3 变量赋值和初始化

变量一旦定义后,就可以通过引用变量来进行赋值等操作。所谓引用变量,就是使用变量名来引用变量的内存空间。由于变量是内存空间的一个标识,因此对变量的操作也是对其内存空间的操作。例如:

int  x,  y;
x=8;                         /* 给x赋值 */
y=x;                         /* 将x的值赋给y*/

“x = 8;”和“y = x;”都是变量的赋值操作,“=”是赋值运算符。由于变量名x和y是它们的内存空间的标识符(名称),因此,“x = 8;”是将运算符“=”右边的数据8存储到左边变量x的内存空间中。而“y = x;”这一操作则包括两个过程:先获取x的内存空间中存储的值(此时为8),然后将该值存储到y的内存空间中。其操作过程可用图2.5来表示。

图2.5 “x = 8; ”和“y = x;”赋值操作

当首次引用一个变量时,变量必须要有一个确定的值,这个值就是变量的初值。在C语言中,可用下列方法给变量赋初值。

(1)在变量定义后,使用赋值语句来赋初值。如前面的“x = 8;”和“y = x;”,使x和y的初值都为8。

(2)在变量定义的同时赋给变量初值,这一过程称为变量初始化,此时的“=”不是赋值运算符,而是初始化的特征符。例如:

int  nNum1=3;                /* 指定nNum1为整型变量,初值为3*/
double    x=1.28;              /* 指定x为双精度实变量,初值为1.28*/

(3)也可以在多个变量的定义语句中单独对某个变量进行初始化,如:

int    nNum1,  nNum2=3,  nNum3;

表示nNum1, nNum2,nNum3为整型变量,但只有nNum2的初值为3。

注意:一个没有初值的变量并不表示它所在的内存空间没有数值,而是取决于编译器为其开辟内存空间时的处理方式,它可能是系统默认值或是该内存空间以前操作后留下来的数值,称为无效值

总之,C语言中的变量是某个内存空间的标识,它通常有3个基本要素:C合法的变量名、变量的数据类型和变量的数值;在变量使用之前,必须先对它进行定义。