1.1 一维数组的声明与字符数组

1.1.1 一维数组的声明与初始化

1.一维数组的声明

一维数组声明应指出以下三点:

1)存储在每个元素中的值的类型;

2)数组名;

3)数组中的元素数,数组的元素数必须用值大于等于1的常量表达式定义。

数组定义中的类型可以是内置数据类型或类类型;除引用之外,数组元素的类型还可以是任意的复合类型。数组定义中类型不能是引用,即没有引用数组,这是因为引用是不能赋值的,而数组中的元素必须可以被赋值。

例1:如下定义是否正确?

            int& a[10];

解答:定义错误。VC++6.0提示arrays of references are illegal。

虽然没有引用数组,但数组可以有引用。

例2:定义数组a的引用。

            int  a[6]={0, 2, 4, 6, 8, 10};

解答:int (&p)[6]=a;

如上,p是数组a的引用。数组的引用可以用于函数实参传递。此时可确保传递过来的数组长度合乎要求。

2.一维数组的初始化

在定义数组时,可为其元素提供一组用逗号分隔的初值,这些初值用花括号{}括起来,称为初始化列表。

数组元素初始化时,若没有显式提供元素初值,则元素会被像普通变量一样初始化:

1)函数体外定义的内置类型数组(即内置类型的全局数组),元素初始化为0;

2)函数体内定义的内置类型数组,元素无初始化(注意,若只初始化部分元素,其后的元素此时也会被初始化为0);

3)如果不是内置类型,则不管其在哪定义,自动调用其默认构造函数为其初始化,若该类无默认构造函数则会报错。

例1:给定如下代码:

            int x[4]={0}; int y[4]={1};

数组x和y的值为__________?(2011·阿里巴巴)

A.{0,0,0,0},{1,1,1,1}

B.{0,0,0,0},{1,0,0,0}

C.{0,不确定},{1,不确定}

D.与编译器相关

解答:B。

当数组的大小未知时,需要动态声明一维数组,声明格式如下:

            int* a=new int[n];

当数组使用完毕,需要使用:

            delete []a;

释放内存空间。

1.1.2 C风格字符串与字符数组

1.C风格字符串

C风格字符串包括两种:

1)字符串常量

以双引号括起来的字符序列是字符串常量。为了兼容C语言,C++中所有的字符串常量都由编译器自动在末尾添加一个空字符

字符常量'A'表示单个字符A,然而"A"是字符串常量,其表示字母A和空字符(null)两个字符。

2)末尾添加了'\0'的字符数组。

可见,C风格字符串末尾必须有一个字符'\0'。

例1:下列 是不正确的字符常量?(2012·中兴)

A.'n'

B.'l'

C."a"

D.'\101'

解答:C。C选项是一个字符串常量,其包含字符'a'与空字符两个字符。

例2:下列哪些是C风格字符串?

            char ca1[]={'C', '+', '+'};
            char ca2[]={'C', '+', '+', '\0'};
            char ca3[]="C++";
            const char *cp="C++";
            char *cp1=ca1;
            char *cp2=ca2;

解答:ca1和cp1不是C风格字符串:ca1是一个不带结束符null的字符数组,而指针cp1指向ca1的首字符,因此,它指向的并不是以null结束的数组。其他的声明则都是C风格字符串。

2.字符数组

字符数组既可以用一组由花括号括起来、逗号隔开的字符常量进行初始化,也可以用一个常量字符串(末尾有空字符)进行初始化。如下:

            方式1:char ca1[]={'C', '+', '+'};      // 末尾没有null字符
                  char ca2[]={'C', '+', '+', '\0'}; // 末尾显式地添加null字符
            方式2:char ca3[]="C++";                // 末尾自动添加null字符

然而,要注意这两种初始化形式并不完全相同,因为字符串常量包含一个额外的空字符(null)用于结束字符串。当使用字符串常量值来初始化创建的新数组时,将在新数组末尾加入空字符。

故ca1的长度是3,而ca2和ca3的长度则是4。

注意:字符数组ca2与ca3都可被称为C风格字符串,而字符数组ca1不是C风格字符串。

使用方式2中C风格字符串初始化字符数组时,一定要记得添加在末尾的空字符。

例1:下面的初始化是否正确?

            const  char  ch3[6]="Daniel";

解答:上述C风格字符串包含了6个显式字符,而存放该字符串的数组必须有7个元素,其中6个用于存储字符常量值,而1个用于存放空字符。故将导致编译时的错误。

例2:给出以下定义, 则正确的叙述为______。(2011淘宝)

            char x[]="abcdefg";
            char y[]={'a', 'b', 'c', 'd', 'e', 'f', 'g'};

A.数组x和数组y等价

B.数组x和数组y长度相同

C.数组x的长度大于数组y的长度

D.数组x的长度小于数组y的长度

解答:C。“printf("%d\n", sizeof(x));”输出8;“printf("%d\n", sizeof(y));”输出7。

因为x数组是C风格字符串,后面还有结束符:'\0',所以长度为8;

而y数组就是普通的字符数组,没有'\0'结束符,所以长度为7。

C/C++中有很多字符串处理函数(strcpy、strcat等),传递给这些标准库函数例程的指针必须具有非零值,并且指向以null结束的字符数组(例2中的数组x可传递给这些函数,而y不能)中的第一个元素。其中一些标准库函数会修改传递给它的字符串,这些函数将假定它们所修改的字符串具有足够大的空间接收本函数新生成的字符,程序员必须确保目标字符串足够大。

在使用处理C风格字符串的标准库函数时,牢记参数必须以结束符null结束:

            char  ca[]={'C', '+', '+'};
            cout << strlen(ca) << endl;

在上述代码中,ca是一个没有null结束符的字符数组(即ca不是C风格字符串),计算的结果不可预料。标准库函数strlen总是假定其参数字符串以null字符结束,当调用该标准库函数时,系统将会从实参ca指向的内存空间开始一直搜索结束符,直到恰好遇到null为止。strlen返回这一段内存空间中总共有多少个字符,无论如何这个数值不可能是正确的。

例3:下面程序段的运行结果是(  )。(2012·迅雷)

            char  c[5]={'a', 'b', '\0', 'c', '\0'};
            printf("%s", c);

A.'a"b'

B.ab

C.ab_c

D.ab_c_(其中_表示空格)

解答:B。字符串输出遇'\0'终止。

关于字符串处理函数的更多介绍请参考后续章节。