第1个回答 2010-12-17
要回答你的这个问题,不妨先根据你的问题先编写一段小的示例程序:
#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]在数值上相等。当然,此处仍非等价关系。
至于指向行的指针,所指的就是指向行首位置的指针量。
至于你的最后一个问题,正如我刚才一直强调的那样,等号两端仅仅是数值上的相等,而非等价关系,因此无法按照你所设想的方式进行归纳推导。本回答被提问者和网友采纳
第2个回答 2010-12-17
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.关于这点,本人也没有深究过,但作为过来人,我想说的是,不要死扣语法,语法这东西是人定的,不是计算机定的,如果你实在要去研究这个***,那去学汇编,这可以帮助你。
第3个回答 2010-12-17
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语言编译器里的计算方法造成的。
对于这些繁琐不实用的东西,不要深究,不要用它。
第4个回答 2010-12-18
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.
希望对你有帮助,回答不正确的地方,请楼主海涵。
另外,希望楼主多看课本,多写程序,这样才会有丰富的经验。