关于指针和运算符的值

时间:2018-07-31 05:14:18

标签: c arrays pointers

....
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”运算符将在数组中给出相应的值,但是在这里获取地址,很困惑!

3 个答案:

答案 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)

让我们打印&bb

#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

&bb都引用相同的地址。 数组的地址和数组的第一个元素的地址在数字上相同,但它们的类型不同

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 的示例中:
bb[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的地址来看到这一点。