user-0 提问: 关于指针

回复:
user: user-1
content: 引用 12 楼 qq_41985711的回复:[quote=引用 11 楼 qq_41985711的回复:]int *p = &a[0]; 因为二维数组的首元素是a[0]这个数组，所以p要指向a[0]这个数组，就是 *(p+i) 二维数组的第i个元素，也就是二维数组第i个元素的数组名，所以这是一个指针，指向的是二维数组里第i个元素里的第一个元素。而*(*(p+i)+j) 就是二维数组第i个元素里的第j个元素。区别就是 p = a;这个语句指针p指向的内容只有一个字节，而 p = &a[0]指向的是20个字节。 p = &a指向的是16个字节的内容，打错了[/quote] 又打错了  p =&a[0]指向的是16个字节

user: user-1
content: 引用 11 楼 qq_41985711的回复:int *p = &a[0]; 因为二维数组的首元素是a[0]这个数组，所以p要指向a[0]这个数组，就是 *(p+i) 二维数组的第i个元素，也就是二维数组第i个元素的数组名，所以这是一个指针，指向的是二维数组里第i个元素里的第一个元素。而*(*(p+i)+j) 就是二维数组第i个元素里的第j个元素。区别就是 p = a;这个语句指针p指向的内容只有一个字节，而 p = &a[0]指向的是20个字节。 p = &a指向的是16个字节的内容，打错了

user: user-1
content: int *p = &a[0]; 因为二维数组的首元素是a[0]这个数组，所以p要指向a[0]这个数组，就是 *(p+i) 二维数组的第i个元素，也就是二维数组第i个元素的数组名，所以这是一个指针，指向的是二维数组里第i个元素里的第一个元素。而*(*(p+i)+j) 就是二维数组第i个元素里的第j个元素。区别就是 p = a;这个语句指针p指向的内容只有一个字节，而 p = &a[0]指向的是20个字节。

user: user-2
content: 引用 8 楼 fafactx 的回复:所有多维数组在内存里均是一纬数组存的。 太武断了你。 参考#5

user: user-3
content: 你的p定义为int* 类型，但是却解引用了两次，肯定有问题。

user: user-4
content: 2楼说的在理，实质上还是类型不匹配的原因。

user: user-5
content: 可以从*(*(p + i)这里思考一下： 楼主那么定义显然p和a是不等价的 首先p是int*的，而a虽然本质上也是个地址但是最起码也是个int**，否则不会有*(*(p + i)这种操作。 但是即使是int** p; p和a也不是等价的。因为指针的“+"操作是需要知道所指向的类型的。*（p+1）到底是指向下一个元素，还是下一行呢？无法知道。因此才会有楼上的这种写法，明确指出（p+1）指针所要移动距离。

user: user-6
content: 所有多维数组在内存里均是一纬数组存的。

user: user-7
content: #include<stdio.h> int main() {     int a[3][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };     int i,j;     int (*p)[4] = a;     for (i = 0; i < 3; i++)     {         for (j = 0; j < 4; j++)         {             printf("%2d  ", *(*(p + i) + j));         }         printf("\n");     }     return 0; } 改成这样就可以了。类型不匹配

user: user-8
content: 楼主：个人理解，int * p=a;代码是应该指向a二维数组的开始地址a[0]或者&(a[0][0])，而二维数组的存储应该是连续的地址，在代码*(*(p + i) + j)中，(p + i) 表示p向后移动 i 个 int类型大小的内存距离，即p指向新的内存位置(p +i )，而代码*(p + i) 表示去(p+i)指向的内存位置的内容值，即*(p + i)已经表示一个值了，而不是表示一个地址了。而代码*(p + i) + j当然也是表示值了，再代码*(*(p + i) + j)，再值的前面加上*字符，应该就报错了。因为(*(p + i) + j)表示的值而不是地址了。

user: user-9
content: 类型不匹配，出错行int * p=a;编译器警告为：error: cannot convert 'int (*)[4]' to 'int*' in initialization; 显然，根据错误提示，无法将a的指向整型数组的指针（错误提示中的int (*)[4]）类型转换成指向整型变量的指针p（错误提示中的int*），那么我们将定义改为int (*p)[4] = a;就OK了。后序使用时，p用起来就和a没有差别了。 至于“如果将11行改为printf("%d  ", *(*(a + i) + j));就可以正常输出；”，其实是因为，数组名在使用过程中，可以看做是指向该数组下标为0的元素的指针。先看一维数组int a[3] = {1,2,3};用数组的方式理解，也就是a[0] = 1;a[1] = 2;a[2] = 3; 从指针的角度理解，a就是指向下标元素0的指针， 那么，a+0指向的就是数组元素a[0]的地址，所以*(a+0) 即*a那就是a[0]的值1; 同理，a+1指向的就是数组元素a[1]的地址，*(a+1)就是指向数组a中下标为1的元素a[1]的值2； 类推，a+i指向的就是数组元素a[i]的地址，*(a+i)就是指向数组a中下标为i的元素a[i]的值； 所以a[i] = *(a+i)  有了一维数组的例子，那么对于二维数组a[3][4]来说 元素a[i][j]的指针表达，一步一步来，先将a[i]看做整体，那么有之前一维数组的解释a[j] = *(a+j)，我们有：  a[i][j]= *(a[i] + j) 再用一次一位数组的替换，那么就有  *(a[i] + j)= *(*(a+i)+j) 所以a[i][j]= *(a[i] + j)= *(*(a+i)+j)；也就解释了你说的为什么可以正常输出的原因。 如果要计算a[2][3]，表达方式#include<stdio.h> int main() {     int a[3][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };      printf("地址：*(a+1)+2 = %x, a[1]+2 = %x, &a[1][2] = %x\n",*(a+1)+2,a[1]+2,&a[1][2]);     printf("值：*(*(a+1)+2) = %d, *(a[1]+2) = %d, a[1][2] = %d",*(*(a+1)+2),*(a[1]+2),a[1][2]);      return 0; } 结果就是，三者地址一样，如果要取值，就是有这三种表达。 那么，此处我们将定义修改成： int (*p)[4] = a;也就是因为a代表的是有着3个整型数组元素的数组，而且它的每个整型数组元素又是一个有着4个整型变量的数组；比如a[1]是a数组3个元素中的第2个元素，而a[1]这个元素本身是一个有4个整形变量的数组。这么声明，其实就相当于p=a，就可以编译通过并顺利运行。

user: user-10
content: int * p=a; 这句虽然可以赋值，但编译应该有告警，类型不匹配。 正确用法 1、int *p = &a[0][0];当做一维数组用，打印可以用printf("%d",p[i]); 2、int *p[3];p[i] = a[i];指针数组。

user: user-2
content: http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组