地址引用减法是如何工作的?

huangapple go评论74阅读模式
英文:

How does subtracting an address reference work?

问题

I think the value of z should be 40 because a[5] has 20 elements, and the space between it and a[3] also has 20 elements. However, the actual value of z is 2.

Can anyone explain this concept?

#include <stdio.h>

int main()
{
    int a[10][20];
    int z = &a[5] - &a[3];
    printf("%d\n", &a[3]); // 地址信息为 6421740
    printf("%d\n", &a[5]); // 地址信息为 6421900
    printf("%d\n", z);     // z 的值为 2。为什么?
}
英文:

I think the value of z should be 40 because a[5] has 20 elements, and the space between it and a[3] also has 20 elements. However, the actual value of z is 2.

Can anyone explain this concept?

#include &lt;stdio.h&gt;

int main()
{
    int a[10][20];
    int z = &amp;a[5] - &amp;a[3];
    printf(&quot;%d\n&quot;, &amp;a[3]); // the address information is 6421740
    printf(&quot;%d\n&quot;, &amp;a[5]); // the address information is 6421900
    printf(&quot;%d\n&quot;, z);     // z value is 2. why?
}

答案1

得分: 8

Pointer arithmetic is done in the units of the pointed-to type.

In this case a[5] and a[3] are both elements of an array of type int [20], and &a[5] and &a[3] both have type int(*)[20]. They are 2 array element apart, so the difference between them is 2.

It doesn't matter that the underlying type is also an array.

英文:

Pointer arithmetic is done in the units of the pointed-to type.

In this case a[5] and a[3] are both elements of an array of type int [20], and &amp;a[5] and &amp;a[3] both have type int(*)[20]. They are 2 array element apart, so the difference between them is 2.

It doesn't matter that the underlying type is also an array.

答案2

得分: 2

and the space between it and a[4] also has 20 elements
并且它与 a[4] 之间的空间也有 20 个元素

No, the element of a[4] has the type of array of 20 ints. It is not an int.
不,a[4] 的 element 具有 20 个 int 数组的类型,而不是 int

It is called pointer arithmetics. It does not work on bytes or chars only on the type of pointer.
这被称为指针算术。它不仅适用于字节字符,而且仅适用于指针的类型。

&amp;a[3] has type of pointer to int[20]. &amp;a[5] has type of pointer to int[20] and it located two (2) int[20] arrays from &amp;a[3].
&amp;a[3] 具有指向 int[20] 的指针类型。&amp;a[5] 具有指向 int[20] 的指针类型,并且它从 &amp;a[3] 处定位了两个(2)个 int[20] 数组。

It is much easier to explain using a simpler example.
使用一个更简单的例子来解释会更容易。

{
    double dbl[10];
    for(size_t i = 0; i &lt; 10; i++ )
    {
        size_t distance = (dbl + i) - dbl;
        size_t distancebytes = (char *)(dbl + i) - (char *)dbl;
        printf(&quot;dbl + %zu is %zu double and %zu bytes from dbl\n&quot;, i, distance, distancebytes);
    }
}
dbl + 0 is 0 double and 0 bytes from dbl
dbl + 1 is 1 double and 8 bytes from dbl
dbl + 2 is 2 double and 16 bytes from dbl
dbl + 3 is 3 double and 24 bytes from dbl
dbl + 4 is 4 double and 32 bytes from dbl
dbl + 5 is 5 double and 40 bytes from dbl
dbl + 6 is 6 double and 48 bytes from dbl
dbl + 7 is 7 double and 56 bytes from dbl
dbl + 8 is 8 double and 64 bytes from dbl
dbl + 9 is 9 double and 72 bytes from dbl

https://godbolt.org/z/KoKn8sM5b

英文:

> and the space between it and a[4] also has 20 elements

No, the element of a[4] has the type of array of 20 ints. It is not an int.

It is called pointer arithmetics. It does not work on bytes or chars only on the type of pointer.

&amp;a[3] has type of pointer to int[20]. &amp;a[5] has type of pointer to int[20] and it located two (2) int[20] arrays from &amp;a[3].

It is much easier to explain using a simpler example.

int main(void)
{
    double dbl[10];
    for(size_t i = 0; i &lt; 10; i++ )
    {
        size_t distance = (dbl + i) - dbl;
        size_t distancebytes = (char *)(dbl + i) - (char *)dbl;
        printf(&quot;dbl + %zu is %zu double and %zu bytes from dbl\n&quot;, i, distance, distancebytes);
    }
}
dbl + 0 is 0 double and 0 bytes from dbl
dbl + 1 is 1 double and 8 bytes from dbl
dbl + 2 is 2 double and 16 bytes from dbl
dbl + 3 is 3 double and 24 bytes from dbl
dbl + 4 is 4 double and 32 bytes from dbl
dbl + 5 is 5 double and 40 bytes from dbl
dbl + 6 is 6 double and 48 bytes from dbl
dbl + 7 is 7 double and 56 bytes from dbl
dbl + 8 is 8 double and 64 bytes from dbl
dbl + 9 is 9 double and 72 bytes from dbl

https://godbolt.org/z/KoKn8sM5b

答案3

得分: 2

根据C标准(6.5.2.1数组下标)

> 2. 后缀表达式后跟在方括号[]中的表达式是数组对象的元素的下标指定。下标运算符[]的定义是E1[E2]等同于(*((E1)+(E2)))。由于适用于二进制+运算符的转换规则,如果E1是数组对象(等效地,是数组对象的初始元素的指针),而E2是整数,则E1[E2]指定了E1的第E2个元素(从零开始计数)。

因此,表达式a[3]的求值方式类似于*(a + 3)。因此,表达式&amp;a[3]等效于表达式&amp;*(a + 3),而这又等效于(a + 3)

同样,表达式&amp;a[5]等效于表达式(a + 5)

因此,差异&amp;a[5] - &amp;a[3]的求值方式类似于(a + 5) - (a + 3),其结果为2。也就是说,在这两个地址&amp;a[5]&amp;a[3]之间,只有两个int[20]类型的元素。

另一方面,如果你写(int*)&amp;a[5] - (int*)&amp;a[3],也就是说,如果数组被解释为int类型的一维数组,你将得到2 * 20,这得到了你期望的值40

英文:

According to the C Standard (6.5.2.1 Array subscripting)

> 2 A postfix expression followed by an expression in square brackets []
> is a subscripted designation of an element of an array object. The
> definition of the subscript operator [] is that E1[E2] is identical to
> (*((E1)+(E2))). Because of the conversion rules that apply to the
> binary + operator, if E1 is an array object (equivalently, a pointer
> to the initial element of an array object) and E2 is an integer,
> E1[E2] designates the E2-th element of E1 (counting from zero).

So the expression a[3] is evaluated like *( a + 3 ). As a result the expression &amp;a[3] is equivalent to the expression &amp;*( a + 3 ) that in turn is equivalent to ( a + 3 ).

The same way the expression &amp;a[5] is equivalent to the expression ( a + 5 ).

So the difference &amp;a[5] - &amp;a[3] is evaluated like ( a + 5 ) - ( a + 3 ) that yields 2. That is between these two addresses &amp;a[5] and &amp;a[3] there are only two elements of the type int[20].

On the other hand if you would write ( int * )&amp;a[5] - ( int * )&amp;a[3] that is if the array would be interpreted as a one-dimensional array of the type int you would get 2 * 20 that yields the expected by you value 40.

huangapple
  • 本文由 发表于 2023年3月9日 21:44:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75685439.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定