....
int a[3][3]={0,1,2,3,4,5,6,7,8}
printf("%d",a+1); // output 1
printf("%d",*(a+1)); //output 2
....
为什么输出1和输出2是相同的地址?如果它将具有一维数组,则应用“ value of”运算符将在数组中给出相应的值,但是在这里获取地址,很困惑!
答案 0 :(得分:3)
a+1
和*(a+1)
的值都相同,但是类型不同。
a+1
的类型为int (*)[3]
,而*(a+1)
的类型为int *
。
此外,%d
不是用于打印指针的正确格式说明符。相反,您应该使用%p
printf("a+1 = %p\n", (void*)(a+1)); // output 1
printf("*(a+1) = %p\n", (void*)(*(a+1))); //output 2
编辑
[OP在评论中要求- My question is whey they evaluate to same adress
为了举例说明,请编辑我的答案]
要以一种简单的方式理解这一点,让我们考虑一维数组的示例:
int b[3] = {3,4,5};
b[0] b[1] b[2]
+-----------+
b | 3 | 4 | 5 |
+-----------+
^
|
base address of array (which is also the address of first element)
让我们打印&b
和b
:
#include <stdio.h>
int main() {
int b[3] = {3,4,5};
printf("&b = %p\n", (void*)&b);
printf("b = %p\n", (void*)b);
return 0;
}
输出:
&b = 0x7ffee9f5fa2c
b = 0x7ffee9f5fa2c
&b
和b
都引用相同的地址。 数组的地址和数组的第一个元素的地址在数字上相同,但它们的类型不同。
b
是指向数组第一个元素的指针 1),而&b
是指向三个{{1 }} 。
int
的类型为b
,而int *
的类型为&b
。
我们可以通过执行简单的指针算术来看到差异-将int (*)[3]
添加到这些指针。
当您将1
添加到这些指针时,结果会有所不同,因为类型不同。
1
将产生b+1
[假设整数的大小为address of first element of array b + 4 bytes
个字节]
4
将产生&b+1
base address of b + (3*4) bytes
让我们打印 +-----------+
| 3 | 4 | 5 |
+-----------+
^ ^
b |
|
b+1
+-----------+
| 3 | 4 | 5 |
+-----------+
^ ^
&b |
|
&b+1
和&b+1
的值
b+1
输出:
#include <stdio.h>
int main() {
int b[3] = {3,4,5};
printf("&b = %p\n", (void*)&b);
printf("&b+1 = %p\n", (void*)(&b+1));
printf("b = %p\n", (void*)b);
printf("b+1 = %p\n", (void*)(b+1));
return 0;
}
回到您的2D阵列场景:
&b = 0x7ffeee6e7a2c
&b+1 = 0x7ffeee6e7a38
b = 0x7ffeee6e7a2c
b+1 = 0x7ffeee6e7a30
是a
一维数组的数组。
二维数组的内存视图如下所示
3
+-----------+
a+0| 0 | 1 | 2 | <--- first 1D array
+-----------+
a+1| 3 | 4 | 5 | <--- second 1D array
+-----------+
a+2| 6 | 7 | 8 | <--- third 1D array
+-----------+
是第二个1D数组的基地址[相当于上例中的a+1
]
&b
1)
和&a[1] --> &(*(a+1)) --> a+1
是第二个一维数组的第一个元素的地址[相当于上例中的*(a+1)
]
b
1)
&a[1][0] --> &(*(*(a+1)+0)) --> &(*(*(a+1))) ---> *(a+1)
的类型为a+1
,而int (*)[3]
的类型为*(a+1)
。
让int *
添加到这些指针
1
输出:
#include <stdio.h>
int main() {
int a[3][3]={0,1,2,3,4,5,6,7,8};
printf("a+1 = %p\n", (void*)(a+1));
printf("(a+1)+1 = %p\n", (void*)((a+1)+1));
printf("*(a+1) = %p\n", (void*)(*(a+1)));
printf("(*(a+1)+1) = %p\n", (void*)((*(a+1))+1));
return 0;
}
希望这可以澄清您的所有疑问。
1)
来自C Standards#6.5.2.1
下标运算符[]的定义是E1 [E2]等于(*((E1)+(E2))))。
在上述一维数组a+1 = 0x7ffee167ea1c
(a+1)+1 = 0x7ffee167ea28
*(a+1) = 0x7ffee167ea1c
(*(a+1)+1) = 0x7ffee167ea20
的示例中:
b
与b[x]
相同。
要访问数组*(b+x)
的第一个元素,您将编写b
并获取数组b[0]
的第一个元素的地址,您将执行b
。 / p>
&b[0]
这意味着&b[0] --> &(*(b+0)) --> &(*b) --> b
将给出数组b
的第一个元素的地址。
运算符b
用于获取地址,而运算符&
用于取消引用。这些运算符相继使用时会相互抵消。因此,*
等效于&(*(b+i))
。
答案 1 :(得分:2)
a+1
是数组的地址。
(数组为a[1]
–地址也可以写为&a[1]
。)
*(a+1)
是该地址处的数组(即数组a[1]
)。
将数组作为参数传递时,该值将隐式转换为该数组的第一个元素的地址。
对于您来说,*(a+1)
(即a[1]
)将转换为&a[1][0]
。
数组的地址与该数组的第一个元素的地址相同– &a[1]
表示与&a[1][0]
相同的位置,但类型不同。
答案 2 :(得分:0)
内存中没有2D数组,因为内存是1D。因此所有2D数组都存储为一维数组序列。
第二,无论您在何处仅写入数组名称,都表示该数组第一个元素的地址。
现在,您的代码Java_my_package_name_SomeClass_someMethod()
和a+1
的地址相同,您可以通过将*(a+1)
替换为a
的地址来看到这一点。