C语言 如何减去地址引用?

ryoqjall  于 2023-03-12  发布在  其他
关注(0)|答案(3)|浏览(113)

我认为z的值应该是40,因为a[5]有20个元素,它和a[3]之间的空间也有20个元素,但是z的实际值是2。
有人能解释一下这个概念吗?

#include <stdio.h>

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

mbjcgjjk1#

指针运算以所指向类型的单位进行。
在本例中,a[5]a[3]都是int [20]类型数组的元素,&a[5]&a[3]都是int(*)[20]类型,它们相距2个数组元素,因此它们之间的差为2。
基础类型是否也是数组并不重要。

jhiyze9q

jhiyze9q2#

根据C标准(6.5.2.1数组下标)
2一个后缀表达式后面跟一个方括号[]中的表达式是数组对象的一个元素的下标指定。下标运算符[]的定义是E1[E2]等同于(*((E1)+(E2)))。由于应用于二元运算符+的转换规则,如果E1是数组对象(相当于指向数组对象初始元素的指针)且E2是整数,则E1[E2]指定E1的第E2个元素(从零开始计数)。
因此,表达式a[3]的计算方式与*( a + 3 )相同,结果表达式&a[3]等价于表达式&*( a + 3 ),而表达式&*( a + 3 )又等价于( a + 3 )
同样,表达式&a[5]与表达式( a + 5 )是等价的。
所以&a[5] - &a[3]的差值可以像( a + 5 ) - ( a + 3 )一样计算得到2,也就是说在&a[5]&a[3]这两个地址之间只有两个int[20]类型的元素。
另一方面,如果你写( int * )&a[5] - ( int * )&a[3],也就是说,如果数组被解释为int类型的一维数组,你会得到2 * 20,它产生你所期望的值40

pkln4tw6

pkln4tw63#

它和a[4]之间的空间也有20个元素
不,a[4]的element具有20个int的数组类型。它不是int型。
它被称为指针算术。它不对字节字符起作用,只对指针类型起作用。
&a[3]具有指向int[20]的指针的类型。&a[5]具有指向int[20]的指针的类型,并且它从&a[3]定位两个(2)int[20]数组。
用一个更简单的例子来解释要容易得多。

int main(void)
{
    double dbl[10];
    for(size_t i = 0; i < 10; i++ )
    {
        size_t distance = (dbl + i) - dbl;
        size_t distancebytes = (char *)(dbl + i) - (char *)dbl;
        printf("dbl + %zu is %zu double and %zu bytes from dbl\n", 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

相关问题