Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 关于指针和运算符的值_C_Arrays_Pointers - Fatal编程技术网

C 关于指针和运算符的值

C 关于指针和运算符的值,c,arrays,pointers,C,Arrays,Pointers,为什么输出1和输出2是相同的地址?如果它有1D数组,那么应用'value of'操作符将在数组中给出相应的值,但这里得到的是地址,混淆了 a+1是数组的地址。 (数组是a[1]–地址也可以写入&a[1]) *(a+1)是该地址的数组(即数组a[1]) 将数组作为参数传递时,该值将隐式转换为该数组第一个元素的地址。 在您的情况下,*(a+1)(即a[1])被转换为&a[1][0] 数组的地址与该数组的第一个元素的地址相同–&a[1]表示与&a[1][0]相同的位置,但具有不同的类型。两个a+1和*

为什么输出1和输出2是相同的地址?如果它有1D数组,那么应用'value of'操作符将在数组中给出相应的值,但这里得到的是地址,混淆了

a+1
是数组的地址。
(数组是
a[1]
–地址也可以写入
&a[1]

*(a+1)
是该地址的数组(即数组
a[1]

将数组作为参数传递时,该值将隐式转换为该数组第一个元素的地址。
在您的情况下,
*(a+1)
(即
a[1]
)被转换为
&a[1][0]


数组的地址与该数组的第一个元素的地址相同–
&a[1]
表示与
&a[1][0]
相同的位置,但具有不同的类型。

两个
a+1
*(a+1)
计算为相同的地址,但它们的类型不同

a+1
类型为
int(*)[3]
*(a+1)
类型为
int*

另外,
%d
不是用于打印指针的正确格式说明符。相反,您应该使用
%p

....
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
....

编辑

[OP在评论中提问-
我的问题是它们的评估结果是否相同

要通过举例说明这一点,请编辑我的答案]

以简单的方式理解这一点,让我们考虑一个1D数组的例子:

printf("a+1 = %p\n", (void*)(a+1));  // output 1
printf("*(a+1) = %p\n", (void*)(*(a+1)));  //output 2
让我们打印
&b
b

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
都指同一地址数组地址和数组第一个元素的地址在数字上相同,但类型不同。

b
是指向数组第一个元素的指针,而
&b
是指向三个
int
数组的指针

b
的类型是
int*
,而
&b
的类型是
int(*)[3]

我们可以通过执行一个简单的指针算法来看到差异-向这些指针添加
1

当您将
1
添加到这些指针时,结果将不同,因为类型不同
b+1
将导致数组b+4字节的第一个元素的
地址
[假设整数的大小为
4
字节]
&b+1
将产生b+(3*4)字节的
基址

&b = 0x7ffee9f5fa2c
b  = 0x7ffee9f5fa2c
让我们打印
&b+1
b+1

    +-----------+
    | 3 | 4 | 5 |
    +-----------+
    ^   ^
    b   |
        |
       b+1

    +-----------+
    | 3 | 4 | 5 |
    +-----------+
    ^           ^
   &b           |
                |
              &b+1
回到2D阵列的场景:

a
3
一维数组的数组。 2D阵列的内存视图如下所示

&b = 0x7ffeee6e7a2c   
&b+1 = 0x7ffeee6e7a38
b  = 0x7ffeee6e7a2c
b+1  = 0x7ffeee6e7a30
输出:

#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;
}
#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;
}
#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标准#6.5.2.1

下标运算符[]的定义是E1[E2]与(*(E1)+(E2))相同

在上述1D数组
b
示例的上下文中:
b[x]
*(b+x)
相同

要访问数组
b
的第一个元素,您将写入
b[0]
,要获取数组
b
的第一个元素的地址,您将执行
&b[0]

&b[0]-->&(*(b+0))-->&(*b)-->b

这意味着
b
将给出数组
b
的第一个元素的地址


运算符
&
用于获取地址,运算符
*
用于解引用。当一个接一个地使用这些操作符时,它们会相互抵消效果。因此,
&(*(b+i))
相当于内存中的
b+i
,因为内存是1D,所以没有2D数组。因此,所有二维数组都存储为一维数组的序列

其次,只要只写数组的名称,就意味着该数组的第一个元素的地址


现在,在您的代码
a+1
*(a+1)
计算为相同的地址时,您可以通过将
a
替换为
a[0][0]
的地址来看到这一点,它不是一维数组。在内存中,可能表示为1使用
%d
打印指针是未定义的行为。
a+1
*(a+1)
都是指针,如果要打印它们,应在将它们强制转换为
void*
后使用
%p
。这就是说,
a+1
*(a+1)
将具有相同的值,但类型不同。为什么它们不具有相同的值呢?两个指针都指向内存中的同一点。为什么你会感到惊讶?只需停止使用
%d
打印指针值即可<代码>%d不能与指针一起使用。这两个答案都为拼图提供了有用的部分。做得好。我的问题是,他们对同一地址的评价是什么?类型上的差异可以通过比较
(a+1)+1
(*(a+1))+1
的效果来说明。前者将指向
a[2][0]
,而后者将指向
a[1][1]
@ArijitKarali我已经编辑了我的答案,并给出了示例来解释它们是不同的,但为什么它们计算到相同的地址。
#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;
}
a+1 = 0x7ffee167ea1c
(a+1)+1 = 0x7ffee167ea28
*(a+1) = 0x7ffee167ea1c
(*(a+1)+1) = 0x7ffee167ea20