user-0 提问: 请问这道题我的答案为什么不对？

回复:
user: user-1
content: 楼主这么说，我还是很高兴的，这又给了我继续在这里混的兴趣。

user: user-0
content: 引用 20 楼 均陵鼠侠的回复:[quote=引用 12 楼 早打大打打核战争 的回复:]你的答案是错的，老师的答案是对的。*a实际上是a[0]，不是a[0][0]，是int[3]类型，所以 int a[2][3]={{1,2,3},{4,5,6}}; int i,j;  for(i=0; i<2;i++) for(j=0;j<3;j++) printf("%d ",*(*a+5*i+j)); i=0时输出的是*(a[0]+0)==a[0][0]、*(a[0]+1)==a[0][1]、*(a[0]+2)==a[0][2] i=1时输出的则是*(a[0]+5+0)==a[0][5]==a[1][2]、*(a[0]+5+1)==a[0][6]、*(a[0]+5+2)==a[0][7]，越界了  不，表达式 * a 的确是得到了数组 a 的首元素，但因为这个元素的类型是数组，所以，就表达式 * (* a + 5 * i + j) 而言，它会继续转换为指向数组首元素的指针。即，转换为指向“数组 a 的首元素的首元素”的指针。有点绕，其实就是指向 a [0][0] 的指针。  还有，楼主的答案是正确的，没有任何问题，前面有我的分析过程（虽然我知道基本上没人看，但我还是写出来了）。有不同意见请提出，我们继续讨论。[/quote] 我有认真看了一遍的 感谢您认真仔细的解答对我这个刚接触c语言的小白很有帮助

user: user-2
content: 啊，我是依据楼主的程序写的，但是楼主的程序写错了(当时我也没注意到楼主程序的数组和题目不一样)，所以那个分析的结论无效(不过分析过程还是对的，只是无的放矢了)～～～

user: user-1
content: 引用 12 楼 早打大打打核战争 的回复:你的答案是错的，老师的答案是对的。*a实际上是a[0]，不是a[0][0]，是int[3]类型，所以 int a[2][3]={{1,2,3},{4,5,6}}; int i,j;  for(i=0; i<2;i++) for(j=0;j<3;j++) printf("%d ",*(*a+5*i+j)); i=0时输出的是*(a[0]+0)==a[0][0]、*(a[0]+1)==a[0][1]、*(a[0]+2)==a[0][2] i=1时输出的则是*(a[0]+5+0)==a[0][5]==a[1][2]、*(a[0]+5+1)==a[0][6]、*(a[0]+5+2)==a[0][7]，越界了  不，表达式 * a 的确是得到了数组 a 的首元素，但因为这个元素的类型是数组，所以，就表达式 * (* a + 5 * i + j) 而言，它会继续转换为指向数组首元素的指针。即，转换为指向“数组 a 的首元素的首元素”的指针。有点绕，其实就是指向 a [0][0] 的指针。  还有，楼主的答案是正确的，没有任何问题，前面有我的分析过程（虽然我知道基本上没人看，但我还是写出来了）。有不同意见请提出，我们继续讨论。

user: user-2
content: 题目中的数组是int a[3][5]; 楼主可能为了省事，测试代码用的是int a[2][3]; 但是数组元素计算公式没有改 printf("%d ",*(*a+5*i+j)); 应该是 printf("%d ",*(*a+3*i+j));

user: user-0
content: 引用 16 楼 forever74的回复:[quote=引用 4 楼 m0_55062981 的回复:][quote=引用 1 楼 forever74的回复:]你的答案没错。  老师的错误在于，如果没有耐心分析学生的答案，那就不要出开放式的题目。 那个请问这样运行了代码只有第一行输出正确，其它行都是乱的是哪里出了问题吗？[/quote]  显然是你的验证代码写得不对。[/quote] 是的 非常感谢

user: user-0
content: 引用 17 楼 早打大打打核战争的回复:题目中的数组是int a[3][5]; 楼主可能为了省事，测试代码用的是int a[2][3]; 但是数组元素计算公式没有改 printf("%d ",*(*a+5*i+j)); 应该是 printf("%d ",*(*a+3*i+j)); 对 我代码写错了

user: user-3
content: 引用 4 楼 m0_55062981 的回复:[quote=引用 1 楼 forever74的回复:]你的答案没错。  老师的错误在于，如果没有耐心分析学生的答案，那就不要出开放式的题目。 那个请问这样运行了代码只有第一行输出正确，其它行都是乱的是哪里出了问题吗？[/quote]  显然是你的验证代码写得不对。

user: user-4
content: 结果跟编译器有关？&a[i][j]是个整形数的指针，加1就是地址移动一个整形数位置，*a取的是数组名所代表的指针。那代表的是整形数的指针？整形数组的指针？存在两种解释，若是整形数的指针，结果是一样的;要是整形数组的指针，加1表示地址加了一个数组长度，就访问溢出了，就有问题了。

user: user-5
content: 理解和讨论之前请先学会如何观察！  //char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]   不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！

user: user-5
content: A[B] *(A+B) *(B+A) B[A] //以上四行等价  "abc"[1] *("abc"+1) *(1+"abc") 1["abc"] //以上四行等价  A[0] *(A) 0[A] //以上三行等价

user: user-6
content: int a[][]; 可能的结果是： 系统同步声明了以下几个标记（a[][], *a[], **a;），类似*a操作是不规范但不少系统会支持的标记。 数组的[]标记和指针的*还有引用的&标记，严格的讲，是可以互相取代但却有不同含义或者不同实现的。（&标记比较常用于单个数据，较少应用于数组操作） 过去有不少黑客尝试在不支持指针的系统（比如：Java）中通过null数组获取void指针（好像没有成功，至少没有相关的危害报告）。

user: user-2
content: 你的答案是错的，老师的答案是对的。*a实际上是a[0]，不是a[0][0]，是int[3]类型，所以 int a[2][3]={{1,2,3},{4,5,6}}; int i,j;  for(i=0; i<2;i++) for(j=0;j<3;j++) printf("%d ",*(*a+5*i+j)); i=0时输出的是*(a[0]+0)==a[0][0]、*(a[0]+1)==a[0][1]、*(a[0]+2)==a[0][2] i=1时输出的则是*(a[0]+5+0)==a[0][5]==a[1][2]、*(a[0]+5+1)==a[0][6]、*(a[0]+5+2)==a[0][7]，越界了

user: user-0
content: 引用 6 楼 focuslight的回复:你代码贴出来看看 请您帮忙看看 #include <stdio.h> int main() { 	int a[2][3]={{1,2,3},{4,5,6}}; 	int i,j;  	for(i=0; i<2;i++) 		for(j=0;j<3;j++) 			printf("%d ",*(*a+5*i+j)); }

user: user-0
content: 引用 7 楼 均陵鼠侠的回复:首先，题目本身是值得商榷的。题目中暗示 a 的元素类型为 int，但其实不然。a是一个元素类型为 int [5]的数组。如下图所示，a 是具有3个元素的、元素类型为“具有5个int类型元素的数组”。  表面上看，这是一个扣字眼的无聊话题，但它很重要，尤其是有助于分析含有数组的表达式。言归正传，就题目的实际所指而言，楼主的答案是：  * (* (a + i) + j) * (* a + 5 * i + j)  先来看第一个答案。首先，表达式 a 的类型为 int [3][5]，在这里自动转换为指向数组 a 首元素的指针。数组 a 的元素类型是 int [5]，所以转换为 int (*) [5]；  接着，表达式 a + i 得到另一个指针，指向数组 a 的元素 i，元素的类型是 int [5]；  接着，表达式 * (a + i) 得到指针所指向的实体，即，得到数组 a 的元素 i，元素的类型是 int [5]；  接着，因为数组 a 的元素 i 是数组（即，表达式 * (a + i) 的结果是 int [5] 类型的数组），在这里自动转换为指向其首元素的指针。元素的类型是 int ，所以转换为指向 int 的指针，指向数组 a 的元素 i 的元素 0。  接着，表达式 * (a + i) + j 的结果是指针，指向数组 a 的元素 i 的元素 j；  最后，表达式 * (* (a + i) + j) 的结果是得到数组 a 的元素 i 的元素 j 本身。当然了，在一个需要值的场合，这个左值会执行左值转换，转换为该元素的存储值。  所以，第一个答案是正确的。  再来看第二个答案。首先，表达式 a 的类型为 int [3][5]，在这里自动转换为指向数组 a 首元素的指针。数组 a 的元素类型是 int [5]，所以转换为 int (*) [5]；  接着，表达式 * a 得到指针所指向的实体，即，得到数组 a 的首元素。数组 a 的元素类型是 int [5]，所以是得到一个 int [5] 类型的数组。因为后面要做加法，所以这个数组自动转换为指向其首元素的指针（int *），实际上指向数组 a 的元素 0 的元素 0；  接着，表达式 * a + 5 * i 将刚才的指针向后移动 5 * i 个 int 大小的位置。在 C 语言里，数组的成分具有连续分配的特点，所以，这实际上是得到一个指向数组 a 的元素 i 的元素 0 的指针；  接着，表达式 * a + 5 * i + j 继续移动指针，再移动 j 个 int 大小的位置，得到一个指向数组 a 的元素 i 的元素 j 的指针。  最后，表达式 * (* a + 5 * i + j) 的结果是得到数组 a 的元素 i 的元素 j 本身。当然了，在一个需要值的场合，这个左值会执行左值转换，转换为该元素的存储值。  所以，第二个答案也是正确的。  通过上面的分析可知，表达式 * a 等价于 & a [0][0] 。既然 & a [0] [0] 可以使用，那么 * a 也没有任何问题。 好的 非常感谢

user: user-7
content: 你代码贴出来看看

user: user-0
content: 引用 2 楼 focuslight的回复:运行代码一下，你的答案也对，可能题库里答案没你这种形式。  a表示二维数组a的首地址，而*a表示二维数组a第一行a[0]的首地址。这样在使用的时候就有所区别。比如 对a的操作a[4]表示a的第四行首地址，而对*a的操作(*a)[4]则代表第一行的第4个元素，即a[0][4]。 请问我运行了一下代码只有第一行输出正确其它行都是乱的是哪里出了问题吗？那个题目的正确答案我也试了都是一样的

user: user-0
content: 引用 1 楼 forever74的回复:你的答案没错。  老师的错误在于，如果没有耐心分析学生的答案，那就不要出开放式的题目。 那个请问这样运行了代码只有第一行输出正确，其它行都是乱的是哪里出了问题吗？

user: user-8
content: 题目明确指出五种访问方式, 显然标准答案是最适合的. 楼主的答案仅仅是等价而已. 第5种强调的是从基地址(&a[0][0])出发的一种访问方式. 用*a表达第0个元素的地址,已在第3种方式中体现.

user: user-7
content: 运行代码一下，你的答案也对，可能题库里答案没你这种形式。  a表示二维数组a的首地址，而*a表示二维数组a第一行a[0]的首地址。这样在使用的时候就有所区别。比如 对a的操作a[4]表示a的第四行首地址，而对*a的操作(*a)[4]则代表第一行的第4个元素，即a[0][4]。