第6单元指针 December /十二月 return (n>=1 & n<=12)?month[n]: month[o] 分析:我们知道,只有全局数组和静态局部数组可以赋初值,而随意使用全局数组 和全局变量又会破坏程序的模块化结构,降低程序的可读性。因此,在上述函数中选用静态 局部指针数组存放表示月份的英文名称的各字符串的地址。该数组中的第一个字符串表示输 入错误的月份值时的提示 63指针与数组 指针是一个变量,因此也应该可以参加运算。那么,对指针进行运算的意义是什么? 设有指针p,qtr以及字符型数组 string char *ptr, *qtr char string[6]: DS: 1000B DS:1001 其关系如图6-4所示。 DS:1002 字符型数组 string 从图64中可以看出,DS:1003 DS:1004 指针p指向数组 string的第ps:1005 一个元素,其内容就是该元DS:1006 素的地址1000现在,如果DS:100771000 指针ptr:指向数组 string DS:1008 执行运算 1003 指针qtr:指向字符串之尾 DS:1009 DS: 100A ptr++ DS:100+0003整数变量len 即在指针变量ptr原来 的值上再加1,使其变为 图6-4指针的运算 1001。可以看出,这正是数组中第二个元素的地址,也就是说,指针现在改为指向数组中的 第二个元素了。如果执行运算 ptr + 3 则p的值由1000变为1003,即指向数组 string的第四个元素。由此可以看出在指针变量 上加上一个常数,相当于改变了其中存储的地址值,即改变了指针指向的数组元素。同样, 也可以从指针变量存储的地址值上减去一个常数,此时指针向前移动若干个元素 在图6-4中还有一个指针变量q,指向字符串的结束标志0(即数组 string的第四个元 素)。如果求出这两个指针的差 len qtr-ptr: 可以看出,这正是字符串 string的长度(不含字符串结束符) 由于在C艹+中每个变量、数组和函数的具体地址和相对顺序是由连接程序确定的(局 部变量是动态分配的),在编写程序时无法知道其确切地址和相对顺序,所以对于指向单个
第 6 单元 指针 - 115 - "December" // 十二月 }; return (n>=1 && n<=12)?month[n]:month[0]; } 分 析:我们知道, 只有全局数组和静态局部数组可以赋初值, 而随意使用全局数组 和全局变量又会破坏程序的模块化结构, 降低程序的可读性。因此, 在上述函数中选用静态 局部指针数组存放表示月份的英文名称的各字符串的地址。该数组中的第一个字符串表示输 入错误的月份值时的提示。 6.3 指针与数组 指针是一个变量, 因此也应该可以参加运算。那么, 对指针进行运算的意义是什么? 设有指针 ptr, qtr 以及字符型数组 string: char *ptr,*qtr; char string[6]; 其关系如图 6-4 所示。 从图 6-4 中可以看出, 指针 ptr 指向数组 string 的第 一个元素, 其内容就是该元 素的地址 1000。现在, 如果 执行运算 ptr++; 即在指针变量 ptr 原来 的值上再加 1, 使其变为 1001。可以看出, 这正是数组中第二个元素的地址, 也就是说, 指针现在改为指向数组中的 第二个元素了。如果执行运算 ptr += 3; 则 ptr 的值由 1000 变为 1003,即指向数组 string 的第四个元素。由此可以看出在指针变量 上加上一个常数, 相当于改变了其中存储的地址值, 即改变了指针指向的数组元素。同样, 也可以从指针变量存储的地址值上减去一个常数, 此时指针向前移动若干个元素。 在图 6-4 中还有一个指针变量 qtr, 指向字符串的结束标志 0(即数组 string 的第四个元 素)。如果求出这两个指针的差: len = qtr-ptr; 可以看出, 这正是字符串 string 的长度(不含字符串结束符)。 由于在C++中每个变量、数组和函数的具体地址和相对顺序是由连接程序确定的(局 部变量是动态分配的), 在编写程序时无法知道其确切地址和相对顺序, 所以对于指向单个 DS:1000 DS:1001 DS:1002 DS:1003 DS:1004 DS:1005 DS:1006 DS:1007 DS:1008 DS:1009 DS:100A DS:100B 指针ptr:指向数组string 1003 指针qtr:指向字符串之尾 图6-4 指针的运算 B i g \0 1000 0003 整数变量len 字符型数组string
第6单元指针 变量和函数的指针进行这样的运算是没有意义的。但是无论怎样分配,一个数组内的各元素 的相对位置总是固定的,所以对数组元素的引用除了使用下标以外,还可以通过使用指针运 算来实现,这是C++程序设计的一大特点 例6-3编写一个字符串复制函数 mystrcpy( 算法:我们知道,字符串的定义是以0为结束符的字符序列。因此复制字符串也只 需复制到0为止。设指针 source中存放着原来的字符串的地址,指针 destin中存放着新的字 符型数组的地址,则伪代码算法为 while*source! =0) /如果* source==0则表示原字符串结束 * destin=* source;//复制字符 // source移向原字符串中的下一个字符 destin +t / destin移向新字符数组的下一位置 destin =0 /在新字符串尾部添写一个结束符0 由于这个算法非常直观,所以上面的伪代码其实已经是最终的程序段了。由于C++的表 达式应用非常灵活,所以这段程序也可以写成: while((*destin++= *source++)!=0) 改写后的程序段只使用了半个语句( while语句的后半部分被省略掉了)!但是功能依 然不变,甚至新字符串尾部的0也已经被复制。C++的这种特点,是其程序比较精练的原因, 受到程序员们的偏爱。但是过分的精练也会使程序难以理解,有悖于结构化程序设计的基本 原则4。 程序: / Example6-3:复制字符串 nystrcpy(char *destin, char *source) ile(*source!=0) 4可能有人会说精练的程序效率高,其实这是一种误解。影响程序效率的因素很多,但源代码长度对程序效 率几乎没有直接影响。事实上,程序的效率表现在两个方面,一是程序运行速度,一是程序使用的数据占用 的存储空间大小。通常用相对于程序处理的数据量所执行的机器指令条数的数量级来表示程序的运行效率 (时间)。例如O(n)表示程序运行时间与数据量之间成比例,O(n2)表示程序运行时间与数据量的平方 成比例,运行时间的增长速度大于数据量的增长速度。显然,对于完成同样功能的两个程序来说,如果一个 程序的效率为O(n),另一个程序的效率为O(n2),则前者的效率高于后者。对程序的空间效率也可以 做如此分析。 对于上面的两个程序段来说,可以使用字符串长度表示数据量,通过简单的分析就可以得出结论,它 们的运行速度均为O(n),使用的数据占用的存储空间长度均为2n,所以效率基本相同。至于程序代码本 身的大小,应以编译后生成的目标代码长度为准,实践表明这两段程序所生成的目标代码长度亦相差无几
第 6 单元 指针 - 116 - 变量和函数的指针进行这样的运算是没有意义的。但是无论怎样分配, 一个数组内的各元素 的相对位置总是固定的, 所以对数组元素的引用除了使用下标以外, 还可以通过使用指针运 算来实现, 这是C++程序设计的一大特点。 [例 6-3] 编写一个字符串复制函数 mystrcpy()。 算 法: 我们知道,字符串的定义是以 0 为结束符的字符序列。因此复制字符串也只 需复制到 0 为止。设指针 source 中存放着原来的字符串的地址,指针 destin 中存放着新的字 符型数组的地址, 则伪代码算法为 while(*source!=0) // 如果*source==0 则表示原字符串结束 { *destin = *source; // 复制字符 source ++; // source 移向原字符串中的下一个字符 destin ++; // destin 移向新字符数组的下一位置 } *destin = 0; // 在新字符串尾部添写一个结束符 0 由于这个算法非常直观, 所以上面的伪代码其实已经是最终的程序段了。由于C++的表 达式应用非常灵活, 所以这段程序也可以写成: while((*destin++ = *source++) != 0); 改写后的程序段只使用了半个语句(while 语句的后半部分被省略掉了)!但是功能依 然不变,甚至新字符串尾部的 0 也已经被复制。C++的这种特点, 是其程序比较精练的原因, 受到程序员们的偏爱。但是过分的精练也会使程序难以理解, 有悖于结构化程序设计的基本 原则4。 程 序: // Example 6-3:复制字符串 mystrcpy(char *destin, char *source) { while(*source!=0) 4 可能有人会说精练的程序效率高, 其实这是一种误解。影响程序效率的因素很多, 但源代码长度对程序效 率几乎没有直接影响。事实上, 程序的效率表现在两个方面, 一是程序运行速度, 一是程序使用的数据占用 的存储空间大小。通常用相对于程序处理的数据量所执行的机器指令条数的数量级来表示程序的运行效率 (时间) 。例如 O(n)表示程序运行时间与数据量之间成比例; O(n 2)表示程序运行时间与数据量的平方 成比例, 运行时间的增长速度大于数据量的增长速度。显然, 对于完成同样功能的两个程序来说, 如果一个 程序的效率为 O(n), 另一个程序的效率为 O(n 2),则前者的效率高于后者。对程序的空间效率也可以 做如此分析。 对于上面的两个程序段来说, 可以使用字符串长度表示数据量, 通过简单的分析就可以得出结论, 它 们的运行速度均为 O(n), 使用的数据占用的存储空间长度均为 2n, 所以效率基本相同。至于程序代码本 身的大小, 应以编译后生成的目标代码长度为准, 实践表明这两段程序所生成的目标代码长度亦相差无几