C中两个数组元素地址之间的偏移量

C中两个数组元素地址之间的偏移量,c,arrays,offset,C,Arrays,Offset,我有一个问题要我找出两个数组元素地址之间的偏移量(以字节为单位): 如果C以列主顺序存储数据,则&myArray[3][2]与&myArray[0][0]之间的偏移量(以字节为单位)将为: 按主要顺序,我认为元素的布局如下: [0][0] -- [1][0] -- [2][0] -- [3][0] -- ..... -- [3][2] 所以在我看来,以字节为单位的偏移量是计算[0][0]和[3][2]之间的跳跃次数,并乘以8,因为这是一个双精度数组。然而,让我困惑的是,它使用&运算符来请求偏移

我有一个问题要我找出两个数组元素地址之间的偏移量(以字节为单位):

如果C以列主顺序存储数据,则
&myArray[3][2]
&myArray[0][0]
之间的偏移量(以字节为单位)将为:

按主要顺序,我认为元素的布局如下:

[0][0] -- [1][0] -- [2][0] -- [3][0] -- ..... -- [3][2]
所以在我看来,以字节为单位的偏移量是计算[0][0]和[3][2]之间的跳跃次数,并乘以8,因为这是一个双精度数组。然而,让我困惑的是,它使用&运算符来请求偏移量。这会不会改变答案,因为它是在两个地址之间询问,还是过程仍然相同?我想是一样的,但我不是100%肯定


如果我的想法是正确的,那么这将是8*15字节吗?

2d数组的内存布局将是一个连续的内存块。(根据您的问题)

那将在(你的问题)中详细说明

但是在
C
中,它的存储方式如下

--+--+--+--+--+--+
 0| 1| 2| 3|4 |5 |
--+--+--+--+--+--+

现在你是完全正确的,你可以考虑在<代码> [0 ] [0 ] < /C>和<代码> [3 ] [2 ] < /C>之间跳转,但是有更好的方法来做到这一点而不考虑所有这些,你可以确信它们的偏移将是它们的地址差异。

你可以简单地得到他们的地址并减去他们

ptrdiff_t ans=&a[3][2]-&a[0][0]
;(这基本上是两个要素之间的差距)

这就是答案
printf(“answer=%td”,ans*sizeof(a[0][0]);
(一个间隙=
sizeof(a[0][0])
)[在您的情况下是
双间隙
]

或者更好的办法是

ptrdiff_t ans = (char*)&a[3][2] - (char*)&a[0][0];//number of bytes between them.

我将解释一下为什么
char*
在这里很重要:

(char*)&a[0][0]
&a[0][0]
在值方面都包含相同的内容。(这不够一般)

但它在指针运算中很重要(解释是不同的)

当不使用CAST时,解释是数组元素的数据类型。这意味着现在考虑“代码>双< /代码> s的差异。当您抛出它时,它将结果在代码< char < /代码> -S.

中插入或差异。 为什么会这样呢?因为所有的数据存储器都是可寻址的,而字符是单字节的


这比预期的要复杂得多,首先让我们看看
C

C实际上没有多维数组。在
C
中,它是作为数组数组实现的。是的,这些多维数组元素按行主顺序存储

为了进一步澄清,我们可以查看标准§6.5.2.1

考虑由声明定义的数组对象

      int x[3][5];
这里
x
3x5
int
s数组;更准确地说,
x
是 三个元素对象,每个元素对象是一个由五个
int
s
组成的数组 表达式
x[i]
,它相当于
(*((x)+(i))
x
转换为指向五个整数的初始数组的指针。然后
i
将 根据
x
的类型进行调整,这在概念上意味着 将
i
乘以指针指向的对象的大小, 即一个由五个int对象组成的数组 当在中使用时,间接寻址用于生成一个包含五个整数的数组 表达式
x[i][j]
,该数组依次转换为指针 到
int
s的第一个,因此
x[i][j]
产生一个int

因此,我们可以说
double myArray[5][7];
这里
myArray[3][2]
myArray[0][0]
不是同一个数组的一部分

现在,我们在这里完成了-让我们进入其他内容:

来自标准第6.5.6.9节

减去两个指针后,两个指针都应指向 相同的数组对象,或数组对象的最后一个元素
后一个元素; 结果是两个数组的下标不同 元素

但是这里的
myArray[3]
myArray[0]
表示两个不同的数组。这意味着
myArrayp[3][2]
myArray[0][0]
都属于不同的数组。它们不是最后一个元素。所以减法
&myArray[3][2]&myArray[0][0]
将不由标准定义。


Eric(Eric Postpichil)指出了这个想法。

在行主遍历中,声明是
array[height][width]
,用法是
array[row][column]
。在行主遍历中,除非您超过宽度并“wrap”,否则,单步到下一个数字将显示下一列到下一行。每行向索引中添加
width
,每列添加1,使行成为“主要”索引

为了获得列主等效值,假设下一个值是下一行,当该行超过高度时,它会“换行”到下一列。这可以通过
index=column*height+row
来描述

因此,对于高度为5的数组
数组[5][7]
,索引
[3][2]
产生
2*5+3=13

让我们用一些代码进行验证。只需切换索引的顺序,就可以获得列的主要行为

#include <stdio.h>                                                                                                             

int main() {                                                                                                                   
    double array[7][5];                                                                                                    
    void *root = &array[0][0];                                                                                             
    void *addr = &array[2][3];                                                                                             
    size_t off = addr - root;                                                                                              
    printf("memory offset: %d number offset: %d\n", off, off/sizeof(double));                                                                        
    return 0;                                                                                                              
}
#包括
int main(){
双数组[7][5];
void*root=&数组[0][0];
ptrdiff_t ans = (char*)&a[3][2] - (char*)&a[0][0];//number of bytes between them.
      int x[3][5];
#include <stdio.h>                                                                                                             

int main() {                                                                                                                   
    double array[7][5];                                                                                                    
    void *root = &array[0][0];                                                                                             
    void *addr = &array[2][3];                                                                                             
    size_t off = addr - root;                                                                                              
    printf("memory offset: %d number offset: %d\n", off, off/sizeof(double));                                                                        
    return 0;                                                                                                              
}