指向二维函数指针数组的首地址指向函数的指针数组怎么使用?

实际工作中,有一个类A,现在需要使用多个A对象的指针,这是时候,首先想到的就是指针数组。————————————————————————————————————————————
指针数组与数组指针 ...
先上代码:int a[2][3]={1,2,3,4,5,6};//2行3列的int型数组int **pp=a;//编译出错,不能用二级指针直接指向二维数组int (*p)[3]=a;//对,p是指向一...
1. 二维数组  设有整型二维数组a[3][4]如下:
  它的定义为:
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)举例理解C语言二维数组的指针指向问题
作者:守夜者
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了C语言二维数组的指针指向问题,文中不建议用二级指针来访问二维数组,需要的朋友可以参考下
&& 之前对数组的概念一直没有理解透彻,只觉得数组名就是个常量指针而已,用法和基本的指针差不多。所以当我尝试用二级指针去访问二维数组时,就经常会出错。下面就是刚开始写的一个错误的程序:
#include &stdio.h&
int main()
int iArray[2][3] =
{{1,2,3},{4,5,6}};
int **pArray = NULL;
pArray = iA
printf("array[0][0] = %d\n", pArray[0][0]);
printf("array[1][2] = %d\n", pArray[1][2]);
开始的时候我是这样分析的:本来数组和指针就差不多,一维数组和一维指针对应,那么二维数组名应该和二维指针差不多,所以上面那个程序是没有错的,应该打印出的是1和6。但是当我实际编译运行的时候,却出现了段错误,也就是我访问了不该访问的地址空间。那错误到底出在什么地方呢?正确的程序应该怎么写呢?
&&&& 为了解决问题,不得不让我重新理解数组的含义。仔细翻阅一些书籍后,我发现其实数组并不是我原来想象的那么简单:一个常量指针标识的一群变量的集合。数组应该也算是一个完备的变量类型:有名字,有大小,也有地址。只不多就是名字和它的地址一样罢了。也正是因为数组有大小,所以当用sizeof对数组名进行运算时,算出来的是实际数组的大小,而不是指针的大小。
&&&& 也正是因为这样,所以指向数组的指针和指向指针的指针也大不一样。它们俩最明显的不同就是表现在指针步进的时候。我们知道指针在进行++运算的时候,跨越的实际地址取决于指针指向的数据类型:对于一般的32位机来说,假如指向的是int型数据,跨越的实际地址就是4,指向的是指针型数据,跨越的实际地址也是4,当指向的是数组类型的时候,跨越的实际地址就是数组的长度了。
&&&& 现在再回头分析上面那个错误程序,根据下标引用符号[]的运算规则,我们知道pArray[0][0]其实就是**pArray,而iArray实际上只是个数组变量名,而它的值就是整个数组的开始地址(其实&iArray,iArray,iArray[0]以及&iArray的值都是数组的开始地址,都是在编译过程中编译器赋予的值)。那么其实*pArray就已经是iArray[0][0]的值了,也就是1,而**pArray则是去访问地址为1的地址空间中的数据,自然会出段错误。
&&&& 其实用指针访问二维数组可以直接用一级指针就可以了。比如下面这个程序:
int main()
int iArray[2][3] =
{{1,2,3},{4,5,6}};
int *pArray = NULL;
pArray = iA
printf("array[0][0] = %d\n", *pArray);
printf("array[1][2] = %d\n", *(pArray + 1 * 3 + 2));
&因为数组本身在地址空间中就是连续排列的,根据行数和列数,我们自己计算出访问单元的地址偏移量就可以用一级指针轻松遍历二维数组中的所有数据了。
我们还可以尝试用指向数组的指针来访问二维数组的成员。下面就是事例程序:
int main()
int iArray[2][3] =
{{1,2,3},{4,5,6}};
int (*pArray)[3] = NULL;
pArray = iA
printf("array[0][0] = %d\n", pArray[0][0]);
printf("array[1][2] = %d\n", pArray[1][2]);
&简单分析一下这个程序:我们知道[]运算符的结合方向是由左向右,pArray[1][2]就等价于(* (pArray + 1))[2],而由于pArray是数组指针,而且数组的长度为3,所以* (pArray + 1)就表示iArray[1]这个数组,则pArray[1][2]则就完全等价于iArray[1][2]。
&&&& 如果非得想用二级指针来访问二维数组的话,我们还得借用指针数组(数组内存储的都是指针类型的数据),下面是事例程序:
int main()
int iArray[2][3] =
{{1,2,3},{4,5,6}};
int *ipArray[2] = {iArray[0], iArray[1]};
int **pArray = NULL;
pArray = ipA
printf("array[0][0] = %d\n", pArray[0][0]);
printf("array[1][2] = %d\n", pArray[1][2]);
&& 由于二级指针要跳两次,所以中间还需要额外的存储一级指针的空间。所以一般不建议用二级指针去访问二维数组。
众所周知,指针实质就是地址!一个变量的地址即称为此变量的“指针”。如果有这样一种变量:它的存储单元里存放的是其它变量的地址!我们就称之为“指针变量”。(请注意两者之间的区别:两个完全不同的概念!)
我们都知道,数组名和函数名就是它们的入口地址。同理,一个变量名其实也是此变量的所在地址!C语言中有一种运算符为“&”:取址运算符。因为数组名与函数名本身代表的就是地址,通常不会对并且也不能对它们进行取址操作或其它运算操作(其实对于函数名的直接引用与对它取址是等价的)。这也是它们被称为“常量”的原因!但对于一个变量来讲,情况就不一样了。要想获得它的地址,就必须进行“&”运算,尽管它本身表示的也是地址值!而对变量直接进行引用得到却是它所在的内存单元的数据内容!“指针变量”作为一种变量当然也不能例外!只不过它与其它普通变量的差别是,它的内容是其它变量(包括“指针变量”)的地址,在WIN32上,它的大小恒为32位,4BYTE。而普通变量则不会有大小上的限制!对指针变量所指向的地址的数据内容的获取则是通过操作符“*”。在理解上我们将“提领操作符*”视为类型的一部分,并且这种数据类型是一种变量地址类型(均对每一个“*”而言)!
只要明白了以上常识,“指针”将不会再是程序设计中的“拦路虎”!
从内存的存储映象的角度来讲,C的规则数组(不包括通过数据结构设计的多维数组)不存在多维,也就是说所有的数组本质上都是一维的,而一级指针就等价于一维数组!关键的不同在于多维数组与一维数组语义上的差别!而我们理解多维数组通常将之形象地描述成“矩阵”形式。更为精确的理解是多维数组的每个元素就是一个数组,如此递归下去直至最后每个元素是一个简单的变量类型,最终得到的就是一个特殊的一维数组!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具二维数组&函数指针 - 简书
二维数组&函数指针
先说一下指针的用途:1.访问函数,在函数内部需要改变外部传入内部的值;2.函数中需得到一个连续存储空间的首地址;3.动态分配内存,需要记录分配内存的首地址。说穿了,指针的用途就是和地址相关的。
定义方法  ①int temp1 [2][3] = {};  第一个中括号是“行”,第二个中括号是“列”。
      ②int temp2 [][3] = {1,2,3,4,5,6};  “列数”不需要明确指出。
      ③int temp3 [2][3] = {1,2,3,4};  后两个元素为0。
  char *name[];   这种声明,未分配内存空间。
  字符串的交换不能直接用正常变量的方法进行交换。用&string.h&这个头文件中“strcpy( , )”(逗号后面的将字符串复制给逗号前的字符串)。
图片中的函数就是用自己的方法将“strcpy”函数重新写了一遍。
int add (int a,int b){
int (*pfunction)(int,int) =
//函数指针
int result = pfunction(3,4);
pfunction =
//指向另一个函数
用心做好猿。
C语言笔记 一终端命令 ls -l显示当前工作路径下的所有的文件及文件信息 d开头文件夹 -开头文件 r读 w写 x执行 - -当前用户的权限 - -其他用户的权限 & pwd查看终端程序的工作路径 &cd切换工作路径 &clear清理屏幕 &touch新建文件 &open...
指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环, 能...
C语言基础 二维数组 定义:可以看成多个以为数组构成 int arr[2][3]2代表行数,3代表列数int arr[2][3]={{1,2,3},{4,5,6}}int arr[2][3]={1,2,3,4,5,6}int arr[2][3]={{[1]=3},{[2]=...
iOS面试小贴士 ———————————————回答好下面的足够了------------------------------------- 多线程、特别是NSOperation 和 GCD 的内部原理。 运行时机制的原理和运用场景。 SDWebImage的原理。实现机制。...
__block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。3.__blo...
思考:SCQA架构就好比是FABE法则,可以颠倒使用,也可省略使用,但最终目的都要突出答案。 S:情景,即你要说出某件事情背后的原因。 C:冲突,即这件事情目前存在或矛盾。 Q:问题,即当下正在发生的问题。 A:答案,即你想怎样做。 按照这个架构,再复杂的事情几句话都可以表...
苍凉暮色,依稀孤星照,江边清笛。 霜竹衰草,寂寞昏鹊枯枝,谁人见、幽人独立。 飒飒风,穿窗透户,惊梦起赋词。 . 静听,雨潇潇、声声催花落,香溢新池。 空樽对月,抚琴无心唤旧忆。 流年遍布惆怅,何处藏、寥寥欢喜。 夜深深、久凭栏,冷暖自知。
又是一年寒冬,电话又响起
“啊,啥意思”
因为外婆是湖南人,所以每一年每一次的电话即使说的话的内容完全一致,我都难以理解他背后的意思,每次外婆的电话声响起我都会十分含糊的敷衍过去或者用一些只能哄小孩子的理由推辞掉,现在想想都觉得自己好幼稚,因...
1 scripts字段 scripts指定了运行脚本命令的npm命令行缩写,比如start指定了运行npm run start时,所要执行的命令。 2 dependencies字段,devDependencies字段 dependencies字段指定了项目运行所依赖的模块,...
姓名:杨忠诚 公司:慧友冠源科技&272期六项精进努力二组&广东盛和塾稻牙二组 【日精进打卡第84天】' 【知~学习】 早晨诵读: 《六项精进》大纲2遍共441遍 《六项精进通篇》遍 共45遍 《大学》2遍 共355遍 诵读《忏悔文》,诵读《心经》 学习:阅读《决策智慧》~...查看: 3749|回复: 5
转一个讲解函数指针数组的文章,原来函数指针数组很简单
主题帖子精华
中级会员, 积分 412, 距离下一级还需 88 积分
在线时间121 小时
写了一个函数,里面要在一个地方在不同的时候选择不同的函数,if、switch比较麻烦,想到了这个。可C很烂,这篇文章很明白地讲解了我的疑惑。
******************************************************************************************************
http://www.52rd.com/Blog/Detail_RD.Blog_zjhfqq_7228.html
关于函数指针数组的定义方法,有两种:一种是标准的方法;一种是蒙骗法。
第一种,标准方法:
分析:函数指针数组是一个其元素是函数指针的数组。那么也就是说,此数据结构是是一个数组,且其元素是一个指向函数入口地址的指针。&
根据分析:首先说明是一个数组:数组名[]&
其次,要说明其元素的数据类型指针:*数组名[].&
再次,要明确这每一个数组元素是指向函数入口地址的指针:函数返回值类型 (*数组名[])().请注意,这里为什么要把“*数组名[]”用括号扩起来呢?因为圆括号和数组说明符的优先级是等同的,如果不用圆括号把指针数组说明表达式扩起来,根据圆括号和方括号的结合方向,那么 *数组名[]() 说明的是什么呢?是元素返回值类型为指针的函数数组。有这样的函数数祖吗?不知道。所以必须括起来,以保证数组的每一个元素是指针。
第二种,蒙骗法:
尽管函数不是变量,但它在内存中仍有其物理地址,该地址能够赋给指针变量。获取函数方法是:用不带有括号和参数的函数名得到。
函数名相当于一个指向其函数入口指针常量。 那么既然函数名是一个指针常量,那么就可以对其进行一些相应的处理,如强制类型转换。&
那么我们就可以把这个地址放在一个整形指针数组中,然后作为函数指针调用即可。
完整例子:
#include "stdio.h"
int add1(int a1,int b1);
int add2(int a2,int b2);
int main(int argc,char* argv[])
int numa1=1,numb1=2;
int numa2=2,numb2=3;
int (*op[2])(int a,int b);
op[0]=add1;
op[1]=add2;
printf("%d %d\n",op[0](numa1,numb1),op[1](numa2,numb2));
int add1(int a1,int b1)
return a1+b1;
int add2(int a2,int b2)
return a2+b2;
再给出常用的C变量的定义方式:
a) 一个整型数(An integer)&
b) 一个指向整型数的指针(A pointer to an integer)&
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)&
d) 一个有10个整型数的数组(An array of 10 integers)&
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)&
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)&
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)&
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an
integer )
a) // An integer&
b) int *a; // A pointer to an integer&
c) int **a; // A pointer to a pointer to an integer&
d) int a[10]; // An array of 10 integers&
e) int *a[10]; // An array of 10 pointers to integers&
f) int (*a)[10]; // A pointer to an array of 10 integers&
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer&
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
主题帖子精华
金钱119227
在线时间938 小时
谢谢分享。。。.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子& &
主题帖子精华
中级会员, 积分 403, 距离下一级还需 97 积分
在线时间71 小时
多谢楼主分享
主题帖子精华
初级会员, 积分 66, 距离下一级还需 134 积分
在线时间6 小时
谢谢分享。。。.
主题帖子精华
初级会员, 积分 90, 距离下一级还需 110 积分
在线时间20 小时
收藏了。内容不错
主题帖子精华
金牌会员, 积分 1088, 距离下一级还需 1912 积分
在线时间201 小时
这个是C语言与指针的内容
Powered by为什么不能把二维数组名/行的首地址赋给指针?_百度知道
为什么不能把二维数组名/行的首地址赋给指针?
int a[3]={1,2,3};
//可以通过
int *j=a+1;
//可以通过
int b[][3]={{1,2,3},{4,5,6}};
//不可通过
int *o=b+0
要想直接把一个二维数组名赋给一个指针,这个指针必须是行指针或二级指针才可以;因为在C编程系统中,对于二维数组会看成数组元素为一维数组的一维数组,即对于二维数组aa[2][3],系统会看成aa[0]和aa[1],而aa[0]和aa[1]中分别包含三个元素,这就是系统对于二维数组的处理;所以直接把二维数组名赋给一个普通的指针变量,这个指针是指向元素aa[0]的,但实际上呢,aa[0]不是一个具体的元素,而是元素aa[0][0]的地址;所以只有把数组名赋给二级指针它才指向一个具体的元素。二维数组名不能说是二级指针,不能按指针的思路来理解二维数组,要按一维数组的思路来理解,即按照系统的理解方式会简单些。*(a+0)==&a[0]是第一个一维数组的数组名和首地址 *a==&*(a+0)==&a[0]是第一个一维数组的数组名和首地址 int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}设数组a的首地址为1000。从二维数组的角度来看,a是二维数组名,a代表整个二维数组的首地址,也是二维数组0行的首地址a+1代表第一行的首地址。 a[0]是第一个一维数组的数组名和首地址,因此也为1000。*(a+0)或*a是与a[0]等效的, 它表示一维数组a[0]0 号元素的首地址,也为1000。&a[0][0]是二维数组a的0行0列元素首地址,同样是1000。因此,a,a[0],*(a+0),*a,&a[0][0]是相等的。 同理,a+1是二维数组1行的首地址,等于1008。a[1]是第二个一维数组的数组名和首地址,因此也为1008。&a[1][0]是二维数组a的1行0列元素地址,也是1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的。 由此可得出:a+i,a[i],*(a+i),&a[i][0]是等同的。 此外,&a[i]和a[i]也是等同的。因为在二维数组中不能把&a[i]理解为元素a[i]的地址,不存在元素a[i]。C语言规定,它是一种地址计算方法,表示数组a第i行首地址。由此,我们得出:a[i],&a[i],*(a+i)和a+i也都是等同的。 另外,a[0]也可以看成是a[0]+0,是一维数组a[0]的0号元素的首地址,而a[0]+1则是a[0]的1号元素首地址,由此可得出a[i]+j则是一维数组a[i]的j号元素首地址,它等于&a[i][j]。 由a[i]=*(a+i)得a[i]+j=*(a+i)+j。由于*(a+i)+j是二维数组a的i行j列元素的首地址,所以,该元素的值等于*(*(a+i)+j)。
采纳率:66%
void *p=b,&b[0]是nt (*)[3];都是能通过的。但是没有类型那么同样的一个地址,*b应该是什么?你如果用void *p=b;那么在后面使用直接使用*p的时候会报错。因为编译器不知道p的类型,不知道怎么解释p中的值,&b[0][0]是int*你把b+1, &b[0]+1。希望你看了这些能明白,不明白的话建议你去买本《完全征服C指针》看看,p是int*,*b是int*,b,&b[0]和&b[0][0]地址是同样的值,但意思不一样,&b[0][0]+1打出来看看;当然你把b强制转换成int *int *p = (int *) b。b,想想。如果你想只是放一个地址的话,你应该用void *指针变量是被某种变量类型派生出来的。b是int (*)[3]
本回答被提问者和网友采纳
是有类型的。。,long是1008。。 指针类型不同最大的区别就是运算时偏移的地址不同。。
b并不是int *型的指针,所以不能赋值给p。。。。,
b+1的值为1001,int为
1004,类型不同不能赋值。,是char 型;
假设b=1000
指针和指针不一样。。虽然指针本质上都是一个地址值。同样是
b+1 ,但还是不允许不同类型指针相互赋值,主要是为了防止滥用指针,导致出错也不好察觉,但还是有赋值方法,那就是可以强制转换
int&*p=b;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//不可通过int&*o=b+0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//不可通过int&*u=b+1&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//不可通过b是二维数组,即使退化也是int**int&*i=*b;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//可以通过int&*y=*(b+0);&&&&&&&&&&&&&&&&&&&&&&&&&&&&//可以通过int&*t=*(b+1);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//可以通过这里的*b、*(b+0)、*(b+1)相当于b[0]、b[0]、b[1]类型是int*。
其他1条回答
为您推荐:
其他类似问题
二维数组的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 指向二维数组的指针 的文章

 

随机推荐