`
fantaxy025025
  • 浏览: 1250334 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

C语言数组与指针学习总结【摘,有改动】

 
阅读更多

=

=

=

https://blog.csdn.net/grey_csdn/article/details/56971681 

C语言数组与指针学习总结【摘,有改动】

 

 

工作之后最害怕的是对最基础知识的考查,因此还是有必要随时回炉学习,温故知新。今天再次回顾总结一下C语言数组相关知识。主要是学习《C语言陷阱与缺陷》的学习笔记。

       C语言数组值得注意的有两点:

       1,C语言中只有一维数组,而且数组的大小必须在编译时期就确定下来(旧标准)。然而,C语言数组的元素可以是任意对象,包括数组。这样就给多维数组的实现或者仿真提供了可能。

       2,对于数组,我们只能够做两件事(不同于指针)一是获取数组的大小,二是获得指向数组下标为0的元素的指针其他的任何操作虽说看起来像是数组,但是本质上其实都是基于指针的操作

       以上两天总结摘取自《C语言陷阱与缺陷》,让我想起了之前自己看过的国外的一份C语言数据结构与算法的讲义。其中关于C语言数组与指针的知识给了一个重点关注点的概括——除了作为sizeof的参数以外,其它时候C语言数组的名称跟指向数组首元素的指针是等价的。

       关于C语言中数组的运算机制如何实现是关系到对数组理解的一个重点。其实,这就是要学会(或者说是记住)C语言数组声明定义的形式以及含义。

       1,int a[3];

              定义了一个元素个数为3个的数组a,其中每个元素都是int类型。

       2, struct

{

       int p[4];

       double x;

}b[17];

定义了一个元素个数为17个的数组b,其中每个元素都是一个结构体。

       3,int a[12][31];

              声明定义了一个数组a,该数组有12个元素,其中每个元素是一个拥有31个元素的数组,每个最小子元素的类型都是int。这个地方理解时候一定不能够按照前面两个例子的顺序,从左到右一个个数字字符进行解析。需要记住的还是最前面的那一点,C语言中只有一维数组,而数组名称后面跟着的第一个数字维度就是数组的真实维度。除此之外,其他的参数则是数组元素的信息描述。

       数组名称与指向数组的指针的等价之处在两种表示的等价,如果定义了一个数组a,那么数组的下表为i的元素可以表述为:

       *(a + i) 或者a[i]

       实际上,后者只是前者的一种常用的简写方式。

       而由于上面这种描述,其实a[i]和i[a]表示的含义一样(不能这样的,这是面向编译器编程的了!!!但是知晓原理确实不错的。)。编写如下测试代码;

#include"stdio.h"

 int a[5] ={1,2,3,4,5,};

 int main(void)

{

       printf("%d\n",a[3]);

       printf("%d\n",3[a]);

       return 0;

}

       其中,数组定义的时候我故意在最后的元素后面加上了一个逗号(这是可以的)。其实,这并不是错误。本来我也不是很理解这种方式,在对了《UNIX编程艺术》一书之后才明白。其实,这算是C语言设计的一个优秀的特点,这种特征不仅方便数组元素的扩充时候的修改,而且方便数组的工具生成。程序的编译以及运行记录如下;

 

4

       由上面的验证可以得出先前陈述的结论或者推论。

       接下来通过简单的代码,回顾二维数组与指针的关系基础知识。编写代码如下:

E:\WorkSpace\01_编程语言\01_C语言\01_C语言陷阱与缺陷\exp02>gccexp02.c

#include"stdio.h"

 

int a[12][31];

int *p;

int i;

 

int main(void)

{

       p = a[4];

       printf("value of p: %p\n",p);

       printf("size of a[4]:%d\n",sizeof(a[4]));

       a[4][7] = 3;

       i = a[4][7];

       printf("value of i: %d\n",i);

       i = *(a[4] + 7);

       printf("value of i: %d\n",i);

       i = *(*(a + 4) + 7);

       printf("value of i: %d\n",i);

       return 0;

}

       编译后,运行结果如下:

E:\WorkSpace\01_编程语言\01_C语言\01_C语言陷阱与缺陷\exp02>a

value of p:00405630

size of a[4]: 124

value of i: 3

value of i: 3

value of i: 3

       其中,a[4]的含义自然是代表数组a的下标为4的元素,而元素的为31个int类型对象。通过计算其占用的空间可以看出这一点。而进一步来看,其实a[4]应该是一个31个元素的数组的数组名。这样,a[4]也就等同于这个数组的首地址。在程序中,我通过指针赋值的方式输出了这个地址数值。接下来的元素取值就值得去品味一下了:

       第一次i取值:使用了数组名后面加中括号指明偏移来实现;

       第二次i取值:进一步把第一步中的方式改成了指针取值的方式,通过首地址加偏移的方式。

       第三次i取值:把迭代着的一个数组进一步展开。从最终的形式上看,这种方式比使用下标取值的简写方式要难理解不少。

       最终i的三次输出都是相同的,其实这也算是对三种方式等价的一个最基本的验证。而把a赋值给p是错误的,因为a的含义是一个指向“二维数组的指针”。在代码中加入相应的代码测试的时候,gcc编译器会给出警告。不过,程序还是能够编译通过并运行。

 

 

=

=

=

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics