Chinaunix首页 | 论坛 | 博客
  • 博客访问: 294410
  • 博文数量: 126
  • 博客积分: 7051
  • 博客等级: 少将
  • 技术积分: 1425
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-20 13:21
文章分类

全部博文(126)

文章存档

2008年(126)

我的朋友

分类: C/C++

2008-05-02 08:57:07

   
/*提示:本文内容未全部经过程序测试和经典书籍论证,作者不保证所有内容均完全正确,请正确参考,Copyright @ Shine*/
数组
数组可以看作是一个集合,在内存中占用连续的空间,利用指针访问的时候,它就具有一些特性。
 
Sizeof(arrayname)是比较特殊的,它返回整个数组的长度,不能把它作为指针理解。
例子:
int arry[5];
int len = sizeof(arry)/ arry[0];
利用上面的这个表达式可以获取数组的长度,利用它可以避免数组长度或者是数组类型变化后,需要修改len的情况发生。下面这个方式也是可以的,只是适应性稍差:
#define LEN_MAX 10
int arry[LEN_MAX];
 
P144上半部分解释了为什么不能对下标进行检查的原因,因为标准中没有提及,下标引用不仅仅可以作用于数组,还使用于指针,下标的有效性不仅依赖于指针指向的内容,还依赖于下标的值。
这正是C所能赋予程序员的灵活性和强大的数据获取能力,而灵活性和安全性通常是矛盾的,这就需要程序员去保证正确使用指针。
 
2[array] <=> array[2]
例子:
       char str[] = {'@','c','*','d','a','5','3'};
       printf("%c \n",3[str]);
 
多维数组
关于多维数组的行列解释的问题,关键在于理解内存中如何连续存放数组元素。就好像叫line * col 个人,让你列成纵队或者是列队,这个是绝对的吗?数组的元素可不象人似的,可以定义有脸的为前面。你转个角度,列可以变行,同样行也可以变列。关键就是定 义你看数组的角度问题,然后就不要改变了,这样在你的眼中,数组的行列问题也就统一起来。
 
多维数组的下标实质:多维数组的名字已经不能单纯的看作是一个指针,它随着维数的升高而应当看作是指针,指向指针的指针…(仅仅是利于理解,表 示通过数组名字并不能立即访问到元素,如下面例子最后一条语句,*(array_p + 5)并不是数组元素,而是该元素地址。事实上是指向数组的指针更确切,即它存放的是被拆分为一维时的数组地址)
例如:
       int array_p[2][3] = {{0,1,2},{3,4,5}};
       int (*p)[3] = array_p;
       printf("%d \n", (p + 1));
       printf("%d \n", array_p[1]);
       printf("%d \n", (*(p + 1) + 2));
       printf("%d \n", &(array_p[1][2]));
       printf("%d \n", *(*(p + 1) + 2));
       printf("%d \n", *(array_p + 5));
 
通过(*p)[2]来看指针的解读,关于函数指针以及其他的指针,网络上有很多文章解读和理解。
首先要理解*运算的优先级,这样就不会对*p[2]和(*p)[2]理解不清楚了。
*是和p结合在一起的,表示的意思就是p这个符号表示的是一个指针,它指向什么类型呢?如果没有[2],它就是一个单纯的int类型。现在有了[2],p就是指向一个整形,长度为2的指针。
函数指针的解读也是类似的。例如int (*fun)(int,char*);和int *fun(int,char*);有什么区别,这个应该可以理解了吧?
 
还是上面的例子代码,指针的变化的确是够丰富的:
       int array_p[2][3] = {{0,1,2},{3,4,5}};
       int (*p)[3] = array_p;
       int *p1 = &(array_p[0][0]);
       printf("%d \n", (p + 1));
       printf("%d \n", array_p[1]);
       printf("%d \n", (*(p + 1) + 2));
       printf("%d \n", &(array_p[1][2]));
       printf("%d \n", *(*(p + 1) + 2));
       printf("%d \n", *(array_p + 5));
       printf("%d \n", *(p1 + 5));
 
就如同vc++的rc资源文件里面会包括所有的字串,把需要在界面中显示的字串放在一个数组里面是非常好的习惯,它将改善程序的可维护性。
例如书中提到的:
Char *str_id[] = {
                            “version 2.302”,
                            “Plot-3D”,
                            “Shine”,
                            “2006-9-11”,
                            “XXX Corporation”,
                            NULL,};//有些定义里面可以允许多余的,存在。
定义的指针数组,每个元素都指向一个常量字符串的地址。至于常量字符串,在vc++中是不允许修改的,但是在有些编译器中,这个值是可以修改的;
       char *str_id[] = {
              "Plot-3D",
              "Ver 2.031",
              "Shine",
              "2006-09",
              "XXX coporation",};
       printf("%s\n",str_id[4]);
       str_id[2][3] = 'A';//compiler pass,but run error! Constant string modify is forbidden in Windows!!
 
       char string_id[][20] = {
              "Plot-3D",
              "Ver 2.031",
              "Shine",
              "2006-09",
              "XXX coporation",};
       printf("%s\n",string_id[3]);
       string_id[2][3] = 'A';
       printf("%s\n",string_id[2]
阅读(469) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~