`
michael-java
  • 浏览: 18194 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
最近访客 更多访客>>
社区版块
存档分类
最新评论

第五章 指向数组的指针

阅读更多

 

讲到第五章了,数组两个字还离不开我们的左右,数组的内容也真多,另一方面也因为数组与指针的关系的确非常密切。

        通常,对于int a[8][9]这个二维数组,我们可以这样定义一个指向它的指针:

int (*p)[9];

这个声明的形式跟人们所熟悉的int *p的形式大相庭径,初学者通常会感到迷惑,不理解的地方大致有四个:

1。为什么会以这种形式声明?

2。(*p)应该如何理解?

3。为什么必须把第二维显式地声明?

4。为什么忽略第一维?

下面我们就一起逐个讨论这四个问题:

1。这种形式是C标准的声明语法规定的,由于本章不是对标准的解释,只是对标准的应用,因此笔者尽量以简洁的方式解释这个声明,详细的讨论将在第七章进行。C标准的声明包含了两部分:

声明:

声明说明符  初始化声明符表opt      (opt的意思是可选)

在声明说明符里面有一项类型说明符,int就是这种类型说明符。而初始化声明符表里面的其中一种形式,就是:

直接声明符 [常量表达式opt]

(*p)[9]就是这种直接声明符加[]的形式。

2。p左边的*在这里不是取值运算符,而是一个声明符,它指出p是一个指针。而()括号是不能去掉的,如果去掉了,由于[]运算符优先级比*高,p就会先跟[]结合,这样p就变成了一个指针数组,而不是指向数组的指针。

题外话:

*p还有一种用法,就是当*是取值运算符的时候,*p是一个左值,表示一个变量,为什么*p是一个变量呢?也许有人会说,因为int i, *p=&i嘛,其实这是结果不是原因。严格来说,i只是一个变量名,不是变量,在编译器的符号表里面,变量名是一个符号地址,它所代表的地址值是它指向的那段内存单元的地址,真正叫变量的是那段内存单元,懂汇编的朋友能很容易地区分出来,在汇编里面,可以这样定义一个变量名:

VARW  DW  10,20

VARW就是一个变量名,它在汇编里面是一个地址,代表了10所在的内存单元这个变量。由于p被初始化为&i,*p指向i所代表的那段内存单元,因此说*p是一个变量。把i称为变量是一种习惯上的统称。

3。定义一个指针的时候,首先必须定出指针的类型,由于这是一个指向数组的指针,如果数组的元素的类型定下来了,那么这个指针的类型也就定下来了。前面说过,C语言的多维数组实质上是数组的嵌套,那么所指向数组的元素必定具有数组类型,也就是说,这个数组的元素是一个具有6个int元素的数组,因此,p定义的时候,必须指定第二维的上界,这样才能把p的类型定下来。

4。有这种疑问的人已经犯了一个错误,没有分清楚什么是指针,什么是数组,以数组的思维模式来看待这个指针p。定义一个数组(非static)的时候,需要在栈中静态分配一块内存,那么就需要知道这块内存的大小,因此定义数组时需要确定各维的上界。而这里只是定义一个指针而已,对于一个指针的定义,需要知道的是它所指向对象的类型,并不需要知道对象的大小,这是多余的。因此,所有指向数组的指针的第一维被忽略。

        以上介绍了如何声明一个指向二维数组的指针,类似地,对一个指向n维数组的指针也可以用同样的方法来声明,如下:

int (*p)[x2][x3]......[xn];

同样可以忽略第一维,而其它维必须指定上界。

        最后再讨论一种很常见的对多维数组的错误理解,有些人常常会以为,二维数组就是二级指针,这种错误的根源,来自于可以把一个二级指针int **p以p[i][j]这种形式使用。首先把数组称为指针就是错误的,第一章笔者已经说明了数组名是地址,不能理解为指针。第二,并非能以p[i][j]这种形式使用,那么p就是一个二维数组了,C标准对数组引用的规定,并没有指定数组引用时[]运算符的左边必须是数组名,而可以是一个表达式。第三,这是一种“巧合”,归根到底是由于C语言的数组实现是数组的嵌套同时C标准把[]运算符转换为类似*(*(a+i)+j)这样的等价表达式造成的,那两个取值运算符“恰好”可以用于一个二级指针。第四,p与p[i]并不具有数组类型,sizeof(p)和sizeof(p[i])的结果只是一个指针的大小4字节。而对于一个真正的数组,p与p[i]都是具有数组类型的地址。

        实际上,int **p只是一个指向一维指针数组的指针,而不是指向二维数组的指针。同样地,对于n级指针,都可以看作一个指向一维指针数组的指针,这个指针数组的元素都是n-1级指针。

分享到:
评论

相关推荐

    C++指针数组和数组指针的详细使用说明(含完整示例)

    数组指针是指向数组第一个元素的指针。它可以用来访问和操作数组中的元素。定义数组指针的方式是在类型标识符后面加上一个星号(*)和一个指向运算符(&)。例如,int (*ptr)[5]表示一个指向包含5个整型元素的数组的指针...

    C语言程序设计-指针与数组.pptx

    通过指针引用数组元素如果指针变量p指向数组中的一个元素,则p+1指向同一数组中的下一个元素。 2 指针与数组 如果p的初始值为&a[0],则: p+i和a+i就是a[i]的地址,或者说它们指向a数组的第i个元素。 *(p+i)或*(a+i)...

    学习C++指向字符数组的指针

     记住:在cout和多数C++表达式中,char数组名、指向char的指针以及用引号括起来的字符串常量都被解释为字符串第一个字符的地址.  5、无法使用string对象初始化char指针,但是string类提供了一个名为c_str的成员...

    指针数组和数组指针C.docx

    指针数组和数组指针。 int* intPtrArray[5]; // 创建一个包含 5 个整数指针的指针数组 int a = 10, b = 20, c = 30, d = 40, e = 50; intPtrArray[0] = &a; // 第一个元素指向整数变量... // 第五个元素指向整数变量 e

    C语言编程 C语言程序设计 C语言入门教程 第8章 善于利用指针 共214页.ppt

    8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针 8.6 返回指针值的函数 8.7 指针数组和多重指针 8.8 动态内存分配与指向它的指针变量 8.9 有关指针的小结

    数组指针、指针数组以及二位数组的深入解析

    int *p[3]与int (*p)[3]的区别*p[3]这个是一个指针数组,它所代表的意思是数组中的每一个元素都是一个指针变量,而(*p)[3],p是一个指针变量,表示指向一个含有3个整型元素的一维数组。 代码如下:int i,j; int a[2]...

    11.第十一章 指针.txt

    第十一章 指针 11.1 理解指针 在计算机中,所有的数据都是存放在存储器中的。一般把存储器中的一个字节称为一个内存单元。为了正确访问内存单元,必须为每个内存单元编号,根据一个内存的编号即可准确找到该内存...

    第5讲 指针高级之指针数组-将若干字符串按字母顺序(由小到大)输出

    将若干字符串按字母顺序(由小到大)输出。 解题思路:定义一个指针数组,用各字符串对它进行初始化,然后排序,但不是移动字符串,而是改变指针数组的各元素的指向。 文件里面代码实现。

    指针的应用程序设计十四.doc

    学会使用数组的指针和指向数组的指针变量; 3. 学会使用字符串的指针和指向字符串的指针变量; 4. 学会使用指向函数的指针变量; 5. 了解指向指针的指针的概念及其使用方法 【实验仪器】 计算机 【实验步骤与内容】...

    C++中一维数组与指针的关系详细总结

    如果使指针p,指向数组的首元素,可以进行操作:int * p=a;或者int *p=&a[0];那么p++,是指向数组中的先一个元素,即a[1];此时*p则是a[1]中所放的值。此时,a[i]=p[i]=*(a+i)=*(p+i)下面举一个例子;直接用a[i]来...

    第三章JAVA 中的数组及字符串.doc

    总结:数组相当于C语言中的指向数组的指针, 数据的初始化有二种形式工:定义是赋值,或初始化(NEW运算后)赋值二种形式。 数据也是对象。 数组的copy; 如:int a[]=new int[10]; int b[]=new int[10]; ...

    指针操作数组的两种方法(总结)

    可以将指针指向数组的任意元素,然后从那里开始访问,只要注意不越界就行了,这说明数组只是将元素连续堆叠,并不需要也没有其他的配置信息存放在数组元素之外的地方或者在头尾等等任何地方,都没有,他只是连续的...

    实验4 数组(4学时)

    以类型int[][]声明一个叫matrix的二维数组变量,将矩阵初始化为一个5个元素的数组。 以下列方式为matrix的内部元素赋值:matrix从零开始循环到其长度值;例如索引为i,在每次迭代中,将matrix[i]指向一个新的整数数...

    C++中指针指向二维数组实例详解

    一维指针通常用指针表示,其指向的地址是数组第一元素所在的内存地址,如下 int ary[4][5]; int(*aryp)[5] = ary; 那么ary[4]相当于int(*aryp),以下理解如此,但参数传递需要知道实参所在 的一维个数,所以传递的...

    C程序设计语言_第2版(带书签目录)

    第五章 指针与数组 5.1 指针与地址 5.2 指针与函数参数 5.3 指针与数组 5.4 地址算术运算 5.5 字符指针与函数 5.6 指针数组以及指向指针的指针 5.7 多维数组 5.8 指针数组的初始化 5.9 指针与多维数组 ...

    明明白白C指针.pdf

    由丁类型的长度是一个宇节,所以,原来是指向数组的第号单元开始的四个字节,此时指向了数组中从第 号单元开始的四个字。 我们可以用一个指针和一个循环来遍历一个数组,看例子: 此处略去为整型数组赋值的代码。 这个例...

    C++Primer视频(初级)下载地址

    第5章关系操作符和逻辑操作符 39.第5章位操作符 40.第5章赋值操作符 41.第5章自增和自减操作符 42.第5章箭头操作符 43.第5章条件操作符和逗号操作符 44.第5章new和delete表达式 45.第5章显式转换 46...

    什么叫C语言指针?C语言的特征是什么?附带详细解析.docx

    使用指针访问数组元素,可以通过将指针指向数组的第一个元素,然后使用指针的递增运算符(++)依次访问数组的每个元素。例如:int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; printf("%d", *p); // 输出1 printf("%d...

    清华大学计算机课程之《C++程序设计》

    ◇ 第五章 函数 - 课前索引 - 第一节 函数的定义 - 第二节 函数的说明 - 第三节 函数的调用 - 第四节 inline函数 - 第五节 函数的递归调用 - 第六节 变量的作用域与存储期 - 第七节 函数的重载 - 第八节 ...

Global site tag (gtag.js) - Google Analytics