【发布时间】:2012-11-14 17:01:15
【问题描述】:
我对 C 中指针和数组声明的基础知识感到困惑。我想知道以下两个语句之间的区别,除了在第二个语句中将数组的基地址分配给 ptr。
int a[2][3]= { (1,2,3),(4,5,6)};
int (*ptr)[3] = &a[0];
请举例说明。 第2行R侧的[3]有什么作用?
【问题讨论】:
我对 C 中指针和数组声明的基础知识感到困惑。我想知道以下两个语句之间的区别,除了在第二个语句中将数组的基地址分配给 ptr。
int a[2][3]= { (1,2,3),(4,5,6)};
int (*ptr)[3] = &a[0];
请举例说明。 第2行R侧的[3]有什么作用?
【问题讨论】:
1.二维数组:
int a[2][3]= { {1,2,3},{4,5,6}};
使用内存中的此语句,您有 2x3 整数,它们在内存中都是相邻的。我想您知道如何访问它们,但如果您不知道,我会澄清一下:
a[0][0] : 1
a[0][1] : 2
a[0][2] : 3
a[1][0] : 4
a[1][1] : 5
a[1][2] : 6
2。指向数组的指针:
int (*ptr)[3] = &a[0];
ptr 指向一个 int[3] 内存块。所以你只能将它分配给一个 int[3] 类型:
ptr= &a[0];
ptr= &a[1];
不同的是,这个指针没有自己的内存,你必须把它赋值给一个int[3]变量或者分配它:
ptr= malloc (2*sizeof(int[3]);
这样就可以使用ptr指向的内存了,如果这样初始化ptr的话:
for(int j=0; j<2; j++)
for(int i=0; i<3;i++)
ptr[j][i]=i+j*3+1;
在这种情况下,您将拥有与 int a[2][3] 相同的内存表示,除了此内存在堆中而不是在堆栈中。您始终可以选择重新分配/释放内存和此内存一旦你的函数终止,它就不会被删除。
【讨论】:
你应该知道 C 中的运算符优先规则:http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedencehttp://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
int (*ptr)[3] 而不是int * ptr [3]
第一个是指向大小为 3 的 int 数组的指针(注意 * 更接近 var 名称)
第二个等于int (*(ptr [3])),它是一个大小为 3 的 int 指针数组。
如果您对如何解释表达式有疑问,也可以使用此站点:http://cdecl.org/。
【讨论】:
a 是行大小为 2 列大小为 3 的二维数组。
而 ptr 是指向大小为 3 的 int 数组的指针
但是您的数组ainitialization 方式不正确
由于您使用了(),所以逗号运算符将生效,并将使用3和6进行初始化,而数组a的其他元素将是0进行实际初始化使用{}
&a[0] 是数组第一个元素的地址(意味着它也会为 a 打印相同的值)。
但是当你对ptr执行指针算术运算时,这个&a[0]就会生效
如果是数组,请记住 3 件事:
--->int *ptr=&a[0][0];第一个元素的地址ptr++会给你下一个元素a[0][1]
---> &a[0] = 第一个元素的地址,但如果你这样做int (*ptr)[3]=&a[0]
然后通过ptr++指针将增加整行的大小,ptr将直接指向下一行意味着现在ptr将指向&a[1]
---> &a = 整个数组的地址,如果你把它保存在int (*ptr)[2][3] =&a 并做ptr++ 指针将增加整个数组的大小。
【讨论】:
a的第一个元素的地址是&a[0]
int *ptr = &a[0][0] 是什么?你能详细说明一下吗
a的第一个元素的第一个元素的地址