周立功手把手教你学C语言编程:用数组,构造一个双重指针
第一章为程序设计基础,本文为1.8.3 指针数组中的第二要点:字符串与指针的指针、第三要点: 字符串与二维数组。
>>>> 1. 字符串与指针的指针
除了作为sizeof或&的操作数外,指针数组的数组名在表达式中等价一个双重指针常量,其右值为数组变量的首地址。比如:
int main(int argc, char *argv[])
其完全等价于
int main(int argc, char **argv)
显然,如果要访问一个指针数组,使用指向指针的指针最为方便,但稍不注意偶尔也会写出错误的程序,详见程序清单 1.45。
程序清单 1.45 一个错误的范例程序
1 #include
2 int main(void)
3 {
4 char **pKeyWord;
5 static char * keyWord[5] = {"eagle", "cat", "and", "dog", "ball"};
6
7 pKeyWord = keyWord;
8 while(**pKeyWord != NULL)
9 printf("%s\n", *(pKeyWord++));
10 return 0;
11 }
由于字符串末尾的空字符或'\0'与空指针或NULL的值0恰好相等,因此上述代码的编译和执行结果都是正确的,但确实是一个错误的示例。因为大多数编译器在编译程序清单 1.45(9)时进行了类型转换,将**pKeyWord由char类型转换成了void *,或将NULL由void *转换成了char类型,但在编译时一般会给出一条警告信息,因为空字符是整数类型,而空指针是指针类型。
之所以写出这样的代码,说明程序员完全没有理解""""和NULL的区别。如果编译器完全禁止char与指针之间的相互转换,则上述代码可能编译失败。由此可见,需要认真对待编译器给出的每一条警告信息,并分析出现警告信息的原因,而不是仅仅编译通过、程序执行结果正确就万事大吉了。
程序清单 1.46针对程序清单 1.45的一种解决方案。其首先判断*keyWord是否为空指针,如果为空指针,则退出循环;如果不是,则输出显示该字符串,然后将pKeyWord加1指向下一个字符串。
程序清单 1.46 用指针数组变量与双重指针变量处理多个字符串
1 #include
2 int main(void)
3 {
4 char **pKeyWord;
5 static char * keyWord[6] = {"eagle", "cat", "and", "dog", "ball", "NULL"};
6
7 pKeyWord = keyWord;
8 while(*pKeyWord != NULL)
9 printf("%s\n", *(pKeyWord++));
10 return 0;
11 }
由于指针类型的数组也是一维数组,因此双重指针的算术运算与普通指针的算术运算十分相似。当pKeyWord指向keyWord时,keyWord[i]、pKeyWord[i]、*(keyWord+i)与*(pKeyWord+i)是等效的访问指针数组变量元素的4种表现形式。keyWord[i]指向了第i个字符串的首地址,即第i个字符串第1个字符的地址。若访问指针keyWord[0]所指向的目标变量,则*keyWord[0]的值是字符串"Monday"的第1个字符M。当然,*keyWord[0]也可以写成*pKeyWord[0]、**keyWord、**pKeyWord等表现形式。
程序清单 1.47是针对程序清单 1.45的另一种解决方案。其首先判断*pKeyWord所指向的是否为空字符串(即只包含&
- 电源软启动的实用设计技巧(07-16)
- 周立功:动态分布内存——malloc()函数与calloc()函数(07-22)
- 周立功“程序设计与数据结构”:深度解剖动态分布内存的free()函数与realloc()函数(07-25)
- 周立功教你学程序设计技术:做好软件模块的分层设计,回调函数要这样写(07-30)
- 周立功教你学C语言编程:教你数组是如何保存指针的(07-31)
- 算法的泛化问题,这些坑你可能都经历过!|周立功教你学软件设计(08-01)