#include<stdio.h>
display(int *q, int row , int col){
int i,j;
for(i=0;i<3;i++) {
for(j=0;j<4;j++) {
printf("%d", *(q+i*col+j));
}
printf("\n");
}
}
main()
{
int arr[3][4]={
1,2,3,4,
5,6,7,8,
8,9,1,0
};
display(*arr,3,4);
}
有人可以帮我理解输出指针的工作原理吗?
输出
1234
3456
8910
答案 0 :(得分:1)
那个指针算术。让我们从头开始:
当*q
是指针时,符号q
称为解除引用指针。
指针是可变的,用于保存内存地址。
int i = 9;
int *q = &i;
您可以在此处将i
的地址指定给指针q
。如果你想
访问指针后面的数据,你有两个选择:
int val = *q;
// or
int val = q[0];
第一个是解除引用。但您也可以使用[]
表示法
用于访问指针后面数据的数组(这就是为什么许多人混淆指针的原因)
和数组,甚至认为它们是相同的)。但是当你的时候这很有道理
指针指向一个数组:
int arr[] = [11,12,13,14,15,16];
int *q = arr;
// also possible, but unnecessary
int *q = &arr[0];
在这种情况下,q
会保存数组arr
开头的地址,所以
q + 1;
更有意义。在这种情况下,您告诉编译器您要访问下一个
在int
指向int
之后的q
。
我们假设int
的大小是32位(4字节) 1 并且
q
指向0x000001000000
然后
Memory Value at address Access through dereferencing index access
0x000001000000 11 q *q q[0]
0x000001000020 12 q + 1 *(q+1) q[1]
0x000001000040 13 q + 2 *(q+2) q[2]
...
请注意,编译器知道类型int
的位数,所以它
自动计算正确的地址。
现在让我们来看看
printf("%d", *(q+i*col+j));
此处i
,col
以及j
和int
个变量,i*col+j
也将是int
。
因此q + 1
中的算法也适用。所以q+i*col+j
返回并且
地址和您*(...)
取消引用并获得价值
指针。
当你只有一个指针开始时,这是一个访问二维数组的好方法。为了更好的解释,请看一下 Tony Tannous&{39}和Vlad from Moscow的答案。
1 int
的实际大小取决于架构。
64位架构最常见的大小是8字节(或64位) 2
2 感谢Keine Lust指出我错误的信息。
答案 1 :(得分:0)
该函数将二维数组解释为像这样的一维数组
1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 1, 0
^ ^ ^
| | |
q + 0 * col q + 1 * col q + 2 * col
表达式q + i * col
将指针定位到每行的开头。添加到表达式的整数值j
将指针放在一行内。
取消引用获得的指针
*(q + i * col + j )
^^^
产生指向值。
实际上这个表达式相当于
q[i * col + j]
二维数组的元素a[i][j]
T a[rows][cols];
其中T
某些类型可以作为一维数组的元素访问,如b[i * cols + j]
,前提是指针b
指向二维数组的第一个对象
在此函数调用中
display(*arr,3,4);
将数组指示符转换为指向其第一个元素的指针。这就是表达式arr
具有类型int( * )[4]
。应用一元运算符*
*arr
给出类型int[4]
数组的第一个“行”,该数组又隐式地再次转换为指向第一行的第一个元素的指针并具有输入int *
。
因此该函数获取指向二维arra的第一个整数对象的指针。
为了使通话更清晰,可以写成
display( &arr[0][0], 3, 4);