记住,数组名实际上是个常量指针,总是指向数组开头。因此下列表达式: b += 3
是无效的,因为该表达式试图用指针算法修改数组名的值。 常见编程错误5.14
尽管数组是指向数组开头的S针,而指针可以在算术表达式中修改,但数组名不可以在算术表达式中修改,囚为数组名实际上是个常量指针。
图5. 20的程序用我们介绍的四种方法引用数组元素(数组下标、用数组名作为指针的指针/偏移量符号、指针下标和指针的指针/偏移量符号,打印数组的的4个元素)。
要演示数组和指针的互换性,还可以看看程序5.21中的两个字符串复制函数copy1和copy2。
这两个函数都是将字符串复制到字符数组中。比较copy1和copy2的函数原型可以发现,函数基本相同(由于数组和指针具有互换性)。这些函数完成相同的任务,但用不同方法实现。
1 // Fig. 5.20: f~g05_20.cpp
2 // Using subscripting and pointer notations with arrays 3
4 #include
6 int main() 7{
8 int b[] = { 10, 20, 30, 40 } ;
9 int *bPtr = b; // set bPtr to point to array b 10
11 cout << \12 << \13
14 for(int i = 0; i < 4; i++ ),
15 cou << \16 17
18 cout << \19 << \2O
21 for (int offset = 0; offset < 4; offset++ ) 22 cout << \23 << *( b + offset ) << '\\n'; 24 25
26 cout << \28 for ( i = 0; i < 4; i++ )
29 cout << \31 cout << \32
33 for ( offset = 0; offset < 4; offset++ ) 34 cout << \35 << * ( bPtr + offset ) << '\\ n'; 36
37 return 0; 38 }
输出结果:
Array b Printed with: Array subscript notation Pointer/offset notation where the pointer is the array name * (b + 0) = 10
* (b + 1) = 20 * (b + 2) = 30 * (b + 3) = 40
Pointer subscript notation bPtr[ 0 ] = 10 bPtr[ 1 ] = 20 bPtr[ 2 ] = 30 bPtr{ 3 ] = 40
Pointer/offset notation *(bPtr + 0) = 10 *(bPtr + 1) = 20 *(bPtr + 2) = 30 *(bPtr + 2) = 40
图5.20 用我们介绍的四种方法引用数组元素
1 // Fig. 5.21: figOS_21.cpp
2 // Copying a string using array notation 3 // and pointer notation. 4 #include
6 void copy1( char *, const char * ); 7 void copy2( char *, const char * ); 8
9 int main() 10 { 11
12 string3[ 10 ], string4[] = \13
14 copy1( string1, string2 );
15 cout << \16
17 copy2( string3, string4 );
18 cout << \19
20 return 0; 21 } 22
23 // copy s2 to sl using array notation 24 void copy1( char *s1, const char *s2 ) 25 {
26 for ( int i = 0; ( s1[ i ] = s2[ i ] ) != '\\0'; i++ ) 27 ; // do nothing in body 28 } 29
30 // copy s2 to sl using pointer notation 31 void copy2( char *s1, const char *s2 ) 32 {
33 for ( ; ( *s1 = *s2 ) != '\\0'; s1++, s2++ ) 34 ; // do nothing in body 35 }
输出结果: string1 = Hello string3 = Good Bye
图5.21 使用数组和指针符号复制字符串
函数copy1用数组下标符号将s2中的字符串复制到字符数组s1中。函数声明一个作为数组下标的整型计数器变量i。for结构的首部进行整个复制操作,而for结构体本身是个空结构。首部中指定i初始化为0,并在每次循环时加1。for的条件“(s1[i]=s2[i])!='\\0',从s2向s1一次一个字符地进行复制操作。遇到s2中的null终止符时,将其赋给s1,循环终止,因为null终止符等于'\\0'。 记住.赋值语句的值是赋给左边参数的值。
函数copy2用指针和指针算法将s2中的字符串复制到s1字符数组。同样是在for结构的首部进行整个复制操作.首部没有任何变量初始化。和copy1中一样,条件(*s1=*s1)!='\\0'进行复制操作。
复引用指针s2,产生的字符赋给复引用的指针s1。进行条件中的赋值之后,指针分别移到指向s1数组的下一个元素和字符串s2的下一个字符。遇到s2中的null终止符时,将其赋给s1,循环终止。
注意copy1和copy2的第一个参数应当是足够大的数组,应能放下第二个参数中的字符串,否则可能会在写人数组边界以外的内存地址时发生错误。另外,注意每个函数中的第二个参数声明为const char*(常量字符串)。在两个函数中,第二个参数都复制到第一个参数,一次一个地从第二个参数复制字符,但不对字符做任何修改。因此,第二个参数声明为常量值的指针,实施最低权限原则。两个函数都不需要修改第二个参数,因此不向这两个函数提供修改第二个参数的功能。
5.9 指针数组
数组可以包含指针,这种数据结构的常见用法是构成字符串数组,通常称为字符串数组(stringarray)。字符串数组中的每项都是字符串,但在C++中,字符串实际上是第一个字符的指针。因此,字符串数组中的每项实际上是字符串中第一个字符的指针。下列字符串数组suit的声明可以表示一副牌:
char‘*suit[ 4 ] = { \,\,\,\; 声明的suit[4]部分表示4个元素的数组。声明的char*部分表示数组suit的每个元素是char类型的指针。数组中的4个值
为”Hearts'’、”Diamonds”、”Clubs”和”Spades”。每个值在内存中存放