C语言、二维数组指针中的 * 和 &
我看的是谭的那本C,有书的可以翻下吧(没书的看我的叙述吧),244、245页,看的我很迷茫啊1、对于二维数组a[3][4],a+i和*(a+i)怎么会是一样的呢?书上的那...
我看的是谭的那本C,有书的可以翻下吧(没书的看我的叙述吧),244、245页,看的我很迷茫啊
1、对于二维数组a[3][4], a+i 和 *(a+i) 怎么会是一样的呢?书上的那种解释我觉得是在回避这个问题,按照他的说法—— a+1不是一个变量存储单元(这点我认同),就谈不上*(a+i)所指向的内容了。所以*(a+i)不是指向内容的,所以它就是地址了?这种逻辑明显是错的啊。
还有最重要的问题就是谭自始至终没有告诉我们这个“解引用操作符”到底是个什么东西,我知道他是把指针带到它所指向的变量,但是这个定义对二维数组不适用,所以它是错的。 我很想知道这个dereference是什么意思~能从构词法或者其它的什么形象的说说吗?谢谢
2、就是这个&符号的问题了,我觉得跟第一个是一样的,书上有一句话是说,&a[i]
和a[i]是一样的,同理&后面是应该跟一个变量名的,然后用这个来取它的地址,那么这里跟的是一个数组名,怎么理解呢?是不是说把数组名看成一个变量呢?
3、书上所讲的指向行的指针、指向列的指针到底是什么意思呢?看不懂
4、既然a+i=*(a+i),那么,可不可以从数学上推导出:*********(a+i)=(a+i) (任意个星号),如果上述推论是正确的话那么我们怎么得到a[i][0]呢?(我记得好像**(a+i)是等于a[i][0]的,所以才有这个疑问)
恳请大家帮助回答一下,或者我说的有什么不对的地方帮忙指出一下,谢谢了~~ 展开
1、对于二维数组a[3][4], a+i 和 *(a+i) 怎么会是一样的呢?书上的那种解释我觉得是在回避这个问题,按照他的说法—— a+1不是一个变量存储单元(这点我认同),就谈不上*(a+i)所指向的内容了。所以*(a+i)不是指向内容的,所以它就是地址了?这种逻辑明显是错的啊。
还有最重要的问题就是谭自始至终没有告诉我们这个“解引用操作符”到底是个什么东西,我知道他是把指针带到它所指向的变量,但是这个定义对二维数组不适用,所以它是错的。 我很想知道这个dereference是什么意思~能从构词法或者其它的什么形象的说说吗?谢谢
2、就是这个&符号的问题了,我觉得跟第一个是一样的,书上有一句话是说,&a[i]
和a[i]是一样的,同理&后面是应该跟一个变量名的,然后用这个来取它的地址,那么这里跟的是一个数组名,怎么理解呢?是不是说把数组名看成一个变量呢?
3、书上所讲的指向行的指针、指向列的指针到底是什么意思呢?看不懂
4、既然a+i=*(a+i),那么,可不可以从数学上推导出:*********(a+i)=(a+i) (任意个星号),如果上述推论是正确的话那么我们怎么得到a[i][0]呢?(我记得好像**(a+i)是等于a[i][0]的,所以才有这个疑问)
恳请大家帮助回答一下,或者我说的有什么不对的地方帮忙指出一下,谢谢了~~ 展开
7个回答
展开全部
1、
我看了你说的这两页,书上的原话是这样的:“在二维数组中,a+i,*(a+i),&a[i],&a[i][0]的值相等,即他们都是同一地址值”,要注意这个字眼“地址值”,也就是说,这几种表达方式并不是内存中存的数值,而是存放数组的地址的值,首先要弄明白,首地址这个概念,如果只写数组名,就代表数组的首地址,比如,一维数组a[9],a就代表数组首个元素的地址即首地址,a[0]是首个元素而&a[0],你可以把&理解成取地址符,即取出存放该数的地址,那么&a[0]就代表数组首个元素的地址了,即首地址,即a和&a[0]是一个意思,
在看二维数组,二维数组只是比一维数组多了一个“首地址”,即列的首地址,比如a[3][4],a[0]代表什么?a[0]是该二维数组第一行的首地址,这个根据前面我所说的能明白么?那么a代表什么呢?这个其实也是首地址,都是代表数组首行首列数据的地址,值是一样的,接下来就要根据上面的思路认真琢磨思考了,a+i代表什么?注意这个i,a[i][j],其中的i代表的是数组的行,j代表的是数组的列,a+i,其实是加了i行,也就是第i行的第一个元素的地址,可以理解成a[i](把a[i]这一行想象成以为数组,根据一维数组的思路思考,就能明白了),即a+i和a[i]的值相等,如书上所说,在根据上面解释一维数组的思路考虑,&a[i][0]代表什么意思?不难理解,这代表的是第i行的首地址,也就是第i行的第一个元素的地址,如书所说,a+i,a[i],&a[i][0]的值是一样的,
还有一个是*(a+i),这个就需要转转脑筋了,二维数组用指针怎么表示?用二维指针即:**a,那么a[3][4]这个数据(注意是一个数值)用指针怎么表示呢?*(*(a+3)+4),必须有两个“*”才行,要不就是一维数组了,里面是*(a+3)这代表的是第三行没错吧,第三行的什么呢?第三行的首地址没错吧,*(a+3)+4代表什么?代表第3行第4个元素的地址,在最前面加个“*”,*(*(a+3)+4)就是a[3][4]了,那么*(a+i)代表什么?代表第i行的首地址没错吧。。。,那么上面说的a+i代表什么呢?看看就知道了,也是第i行的首地址,也就是a+i和*(a+i)的值是一样的,如书所说,这样书上的那句话就都明白了
2、
关于这个问题,确实有点绕,如果能理解你问的第3个问题,这个就有点眉目了。。。
3、
在二维指针当中(注意指针和数组是不一样的,只是有时候表达的东西没什么区别罢了),在二维指针中,分行指针和列指针,比如上面的a[3][4],如果用指针的形式表示的话,一共有3个行指针,一个列指针,每个行指针都仅指向行的首地址,这个列指针指向的是,第一行的首地址,这个如果用图来表示就再好不过了,可是我没办法在这上面画图,就这样表示吧,看下面:
列指针: a
|
行指针1: a[0]—。。。。。。。
行指针2: a[1]—。。。。。。。
行指针3: a[2]—。。。。。。。
4、
我也不知道这样说对不对,反正我没试过,你不仿试试看。。。
其实这些问题都没必要深究,刚开始学这部分,确实是非常难懂,但只要写的程序多了,用的多了,自然而然就懂了,
最后,祝你成功
我看了你说的这两页,书上的原话是这样的:“在二维数组中,a+i,*(a+i),&a[i],&a[i][0]的值相等,即他们都是同一地址值”,要注意这个字眼“地址值”,也就是说,这几种表达方式并不是内存中存的数值,而是存放数组的地址的值,首先要弄明白,首地址这个概念,如果只写数组名,就代表数组的首地址,比如,一维数组a[9],a就代表数组首个元素的地址即首地址,a[0]是首个元素而&a[0],你可以把&理解成取地址符,即取出存放该数的地址,那么&a[0]就代表数组首个元素的地址了,即首地址,即a和&a[0]是一个意思,
在看二维数组,二维数组只是比一维数组多了一个“首地址”,即列的首地址,比如a[3][4],a[0]代表什么?a[0]是该二维数组第一行的首地址,这个根据前面我所说的能明白么?那么a代表什么呢?这个其实也是首地址,都是代表数组首行首列数据的地址,值是一样的,接下来就要根据上面的思路认真琢磨思考了,a+i代表什么?注意这个i,a[i][j],其中的i代表的是数组的行,j代表的是数组的列,a+i,其实是加了i行,也就是第i行的第一个元素的地址,可以理解成a[i](把a[i]这一行想象成以为数组,根据一维数组的思路思考,就能明白了),即a+i和a[i]的值相等,如书上所说,在根据上面解释一维数组的思路考虑,&a[i][0]代表什么意思?不难理解,这代表的是第i行的首地址,也就是第i行的第一个元素的地址,如书所说,a+i,a[i],&a[i][0]的值是一样的,
还有一个是*(a+i),这个就需要转转脑筋了,二维数组用指针怎么表示?用二维指针即:**a,那么a[3][4]这个数据(注意是一个数值)用指针怎么表示呢?*(*(a+3)+4),必须有两个“*”才行,要不就是一维数组了,里面是*(a+3)这代表的是第三行没错吧,第三行的什么呢?第三行的首地址没错吧,*(a+3)+4代表什么?代表第3行第4个元素的地址,在最前面加个“*”,*(*(a+3)+4)就是a[3][4]了,那么*(a+i)代表什么?代表第i行的首地址没错吧。。。,那么上面说的a+i代表什么呢?看看就知道了,也是第i行的首地址,也就是a+i和*(a+i)的值是一样的,如书所说,这样书上的那句话就都明白了
2、
关于这个问题,确实有点绕,如果能理解你问的第3个问题,这个就有点眉目了。。。
3、
在二维指针当中(注意指针和数组是不一样的,只是有时候表达的东西没什么区别罢了),在二维指针中,分行指针和列指针,比如上面的a[3][4],如果用指针的形式表示的话,一共有3个行指针,一个列指针,每个行指针都仅指向行的首地址,这个列指针指向的是,第一行的首地址,这个如果用图来表示就再好不过了,可是我没办法在这上面画图,就这样表示吧,看下面:
列指针: a
|
行指针1: a[0]—。。。。。。。
行指针2: a[1]—。。。。。。。
行指针3: a[2]—。。。。。。。
4、
我也不知道这样说对不对,反正我没试过,你不仿试试看。。。
其实这些问题都没必要深究,刚开始学这部分,确实是非常难懂,但只要写的程序多了,用的多了,自然而然就懂了,
最后,祝你成功
展开全部
要回答你的这个问题,不妨先根据你的问题先编写一段小的示例程序:
#include <cstdio>
#include <cstring>
using namespace std;
int a[3][4];
int main(){
memset(a, -1, sizeof(a));
int i;
for( i = 0; i < 3; i++){
printf("&a[i][0] = %d\n", &a[i][0]);
printf("a + i = %d; *(a + i) = %d;\n", a + i, *( a + i));
printf("a[i] = %d; &a[i] = %d;\n", a[i], &a[i]);
printf("\n");
}
}
这段示例程序在我本地上运行的结果为:
&a[i][0] = 4214816
a + i = 4214816; *(a + i) = 4214816;
a[i] = 4214816; &a[i] = 4214816;
&a[i][0] = 4214832
a + i = 4214832; *(a + i) = 4214832;
a[i] = 4214832; &a[i] = 4214832;
&a[i][0] = 4214848
a + i = 4214848; *(a + i) = 4214848;
a[i] = 4214848; &a[i] = 4214848;
我想看到这个运行结果,你已经有所了解了,下面我再详细说一下:
指针量a作为一个二维数组的指针量,其本质是一个“指向指针的指针”(为了方便,下面称其为双重指针),或者你可以理解为a为int**类型的指针量。当a做加减运算时,得到的结果仍然是一个“双重指针”,即a + i是一个双重指针,它是一个指向了原数组第i行的起始位置的双重指针。
而*(a + i)原来的双重指针解引用后得到的一个指针变量,他是一个指向了原数组第i行的起始位置的“单重指针”。
可以看出,a + i和*(a + i)尽管数据类型不同(前者为双重指针,后者为单重指针),但是他们指向同一块内存地址,因此作为指针量,他们的值是相等的。注意,仅仅是说,他们的值在数学上是相等的,并非说“他们是等价的”。
你的第二个问题亦是同理:
首先,[]作为C语言的操作符,本身即具有“解引用”的语义。明白的说,就是a[i]与*(a + i)是完全等价的,而&a[i]即等价于a + i。由于易知a + i和*(a + i)在数值上相当,那么进行等价带花可以知道,&a[i]和a[i]在数值上相等。当然,此处仍非等价关系。
至于指向行的指针,所指的就是指向行首位置的指针量。
至于你的最后一个问题,正如我刚才一直强调的那样,等号两端仅仅是数值上的相等,而非等价关系,因此无法按照你所设想的方式进行归纳推导。
#include <cstdio>
#include <cstring>
using namespace std;
int a[3][4];
int main(){
memset(a, -1, sizeof(a));
int i;
for( i = 0; i < 3; i++){
printf("&a[i][0] = %d\n", &a[i][0]);
printf("a + i = %d; *(a + i) = %d;\n", a + i, *( a + i));
printf("a[i] = %d; &a[i] = %d;\n", a[i], &a[i]);
printf("\n");
}
}
这段示例程序在我本地上运行的结果为:
&a[i][0] = 4214816
a + i = 4214816; *(a + i) = 4214816;
a[i] = 4214816; &a[i] = 4214816;
&a[i][0] = 4214832
a + i = 4214832; *(a + i) = 4214832;
a[i] = 4214832; &a[i] = 4214832;
&a[i][0] = 4214848
a + i = 4214848; *(a + i) = 4214848;
a[i] = 4214848; &a[i] = 4214848;
我想看到这个运行结果,你已经有所了解了,下面我再详细说一下:
指针量a作为一个二维数组的指针量,其本质是一个“指向指针的指针”(为了方便,下面称其为双重指针),或者你可以理解为a为int**类型的指针量。当a做加减运算时,得到的结果仍然是一个“双重指针”,即a + i是一个双重指针,它是一个指向了原数组第i行的起始位置的双重指针。
而*(a + i)原来的双重指针解引用后得到的一个指针变量,他是一个指向了原数组第i行的起始位置的“单重指针”。
可以看出,a + i和*(a + i)尽管数据类型不同(前者为双重指针,后者为单重指针),但是他们指向同一块内存地址,因此作为指针量,他们的值是相等的。注意,仅仅是说,他们的值在数学上是相等的,并非说“他们是等价的”。
你的第二个问题亦是同理:
首先,[]作为C语言的操作符,本身即具有“解引用”的语义。明白的说,就是a[i]与*(a + i)是完全等价的,而&a[i]即等价于a + i。由于易知a + i和*(a + i)在数值上相当,那么进行等价带花可以知道,&a[i]和a[i]在数值上相等。当然,此处仍非等价关系。
至于指向行的指针,所指的就是指向行首位置的指针量。
至于你的最后一个问题,正如我刚才一直强调的那样,等号两端仅仅是数值上的相等,而非等价关系,因此无法按照你所设想的方式进行归纳推导。
本回答被提问者和网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
1.a[3][4]表示第三行,第四列。
a+i的a是一个数组,他会自动转化为指针,指向数组的第一行,也就是a[0],或者a[0][0],因为第一行的地址起始就是第一个元素地址。所以a[0]和a[0][0]是一样的。所以a+i起始就是a[0]+i,0表示数组的行,i表示列。
*(a+i)其中的a和i同上。
2.a[i]代表一个数值,假设你的数组时int类型,比如a[i]=6;那加上&就表示对该变量取地址,想想,6你怎么取地址还是6,对不对?所以都差不多。
3.你见过int *p;吧,这个数组在运算的时候自动回转化为指针,比如int *p; int a[10];你一定见过
p = a; 这把a赋值给了一个指针,这就说明a在其实是一个指针,又因为a相当于一个指针(他又是数组),我们说二维数组是两个一维数组,所以当然就有指向行与列的指针了。
4.关于这点,本人也没有深究过,但作为过来人,我想说的是,不要死扣语法,语法这东西是人定的,不是计算机定的,如果你实在要去研究这个***,那去学汇编,这可以帮助你。
a+i的a是一个数组,他会自动转化为指针,指向数组的第一行,也就是a[0],或者a[0][0],因为第一行的地址起始就是第一个元素地址。所以a[0]和a[0][0]是一样的。所以a+i起始就是a[0]+i,0表示数组的行,i表示列。
*(a+i)其中的a和i同上。
2.a[i]代表一个数值,假设你的数组时int类型,比如a[i]=6;那加上&就表示对该变量取地址,想想,6你怎么取地址还是6,对不对?所以都差不多。
3.你见过int *p;吧,这个数组在运算的时候自动回转化为指针,比如int *p; int a[10];你一定见过
p = a; 这把a赋值给了一个指针,这就说明a在其实是一个指针,又因为a相当于一个指针(他又是数组),我们说二维数组是两个一维数组,所以当然就有指向行与列的指针了。
4.关于这点,本人也没有深究过,但作为过来人,我想说的是,不要死扣语法,语法这东西是人定的,不是计算机定的,如果你实在要去研究这个***,那去学汇编,这可以帮助你。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
C 语言,指针的麻烦 是 形式逻辑 不成立,也就是我们习惯的 数学 -- 代数学 方式 不成立。
所以 “可不可以从数学上推导出”-- 答案 是 不可以。
C 语言,声明中如果写:
int *a; // 声明 a 是 指针,指向 int
这时语句中 允许出现 *a 和 a, 不允许出现 &a. a表示指向的地址,*a 表示值。
声明中如果写:
int a; // 声明 a 是 整型变量,不是指针
这时语句中 允许出现 a 和 &a, 不允许出现 *a. a 表示值,&a表示a的地址。
我想,你已经看出 让人头痛之处。
int a[3][4]; // 声明 a 是 二维数组,
这时语句中 允许出现 a[j][i], &a[j][i], 不允许出现 *a[j][i].
二维数组的始地址是 &a[0][0].
初学者,掌握我上面说的即可。
a+i 和 *(a+i) 怎么会是一样的呢?-- 这是C语言 不严格性 造成的,C语言 说 二维数组a[][] 的始地址是 &a[0][0], 但也是 &a[0], 也是a.
a+i 呢 是 &a[0][0] + i * [4].
a+i 和 *(a+i) 是一样的 -- C语言里确实如此,这是C语言编译器里的计算方法造成的。
对于这些繁琐不实用的东西,不要深究,不要用它。
所以 “可不可以从数学上推导出”-- 答案 是 不可以。
C 语言,声明中如果写:
int *a; // 声明 a 是 指针,指向 int
这时语句中 允许出现 *a 和 a, 不允许出现 &a. a表示指向的地址,*a 表示值。
声明中如果写:
int a; // 声明 a 是 整型变量,不是指针
这时语句中 允许出现 a 和 &a, 不允许出现 *a. a 表示值,&a表示a的地址。
我想,你已经看出 让人头痛之处。
int a[3][4]; // 声明 a 是 二维数组,
这时语句中 允许出现 a[j][i], &a[j][i], 不允许出现 *a[j][i].
二维数组的始地址是 &a[0][0].
初学者,掌握我上面说的即可。
a+i 和 *(a+i) 怎么会是一样的呢?-- 这是C语言 不严格性 造成的,C语言 说 二维数组a[][] 的始地址是 &a[0][0], 但也是 &a[0], 也是a.
a+i 呢 是 &a[0][0] + i * [4].
a+i 和 *(a+i) 是一样的 -- C语言里确实如此,这是C语言编译器里的计算方法造成的。
对于这些繁琐不实用的东西,不要深究,不要用它。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
1.
a+i和*(a+i)不是一样的,a[i]和*(a+i)才是一样的。a[i]表示数组a第i个元素,而*(a+i)指的是先将a所在地址后移i位以后,读取地址存储的内容,是一样的。请注意这个*,是指针运算符。指针运算符(*)与解引用操作符(*)是一个东西。对指针使用解引用操作符时,直接相当于是对指针指向的对象的一个引用。dereference 用来取出指标所指物体的内容。
2.
为什么a[i]不是变量呢?i不是一直在变么?所以a[i]也是一直在变的。a[i]的地址也就随元素的变化,在变化啊!
3.
二维数组,可以看成线性代数里的行列式,这个懂吧。比如a[i][j],i代表的就是行,j代表的就是列了。这里就有i和j两个变量了,怎么定义指针,不用我教你了吧。其实你不用死掌握概念,会写程序,懂得用法了,就行了。
4.
不可以使用任意个星号,我曾经也是想象力很丰富,后来改掉了这个习惯,不再想象。
5.
希望对你有帮助,回答不正确的地方,请楼主海涵。
另外,希望楼主多看课本,多写程序,这样才会有丰富的经验。
a+i和*(a+i)不是一样的,a[i]和*(a+i)才是一样的。a[i]表示数组a第i个元素,而*(a+i)指的是先将a所在地址后移i位以后,读取地址存储的内容,是一样的。请注意这个*,是指针运算符。指针运算符(*)与解引用操作符(*)是一个东西。对指针使用解引用操作符时,直接相当于是对指针指向的对象的一个引用。dereference 用来取出指标所指物体的内容。
2.
为什么a[i]不是变量呢?i不是一直在变么?所以a[i]也是一直在变的。a[i]的地址也就随元素的变化,在变化啊!
3.
二维数组,可以看成线性代数里的行列式,这个懂吧。比如a[i][j],i代表的就是行,j代表的就是列了。这里就有i和j两个变量了,怎么定义指针,不用我教你了吧。其实你不用死掌握概念,会写程序,懂得用法了,就行了。
4.
不可以使用任意个星号,我曾经也是想象力很丰富,后来改掉了这个习惯,不再想象。
5.
希望对你有帮助,回答不正确的地方,请楼主海涵。
另外,希望楼主多看课本,多写程序,这样才会有丰富的经验。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询