在C编程中,如果一个2-D数组被给定为(int a[5][3]),并且还给定了特定元素(单元格)的基地址和地址,并且必须找到该元素(单元格的索引号(行和列号),我们能找到吗?如果是,如何?
我知道查找地址的公式是这样的
int a[R][C];
地址(a[i][j])=ba+大小(C*i+j);
如果给定ba、R、C、大小和地址(a[i][j])。。。如何找到i和j的值?
为了求2个变量的值,我们需要2个方程。。但我找不到第二个方程式。
-
特定地址减去基地址后,可以得到从基到特定地址的字节大小。
-
如果用
sizeof(ba[0][0])
(或sizeof(int)
)将该大小除以字节,则得到项目数。 -
items / C
给你第一个维度,items % C
给你第二个维度。
因此:
int ba[R][C];
uintptr_t address = (uintptr_t)&ba[3][2]; // some random item
size_t items = (address - (uintptr_t)ba) / sizeof(ba[0][0]);
size_t i = items / C;
size_t j = items % C;
重要的是用一些具有明确定义行为的类型来执行算术,因此uintptr_t
。
如果我做了int* address
,那么address - ba
将是无意义的,因为ba
衰减为类型为int(*)[3]
的数组指针。它们不是兼容的类型。
使用整数除法和余数运算符。
如果您有base
和指向元素elt
的指针,那么有两件事:
-
在"纯数学"术语中,您必须除以数组中元素的大小。
-
在"C"术语中,当你减去指针时,这个除法就是为你执行的。
例如:
int a[2];
ptrdiff_t a0 = (ptrdiff_t)&a[0];
ptrdiff_t a1 = (ptrdiff_t)&a[1];
a1 - a0; // likely 4 or 8.
这可能是4或8,因为无论你使用什么机器,这都可能是int
的大小,而且因为我们对两个数字进行了"纯数学"减法运算。
但如果你让C参与进来,它会试图为你计算:
int a[2];
int * a0 = &a[0];
int * a1 = &a[1];
a1 - a0; // 1
因为C知道类型,而且它是定律,减去的数字会自动除以类型的大小,将指针差转换为类似数组的索引或偏移量。
这很重要,因为它会影响你的数学运算方式。
现在,如果你知道elt
的地址是base + SIZE * (R * i + j)
,你可以用整数除法(这可能会自动为你执行)、减法、更多整数除法以及模或乘来找到答案;减法:
偏移量或数字=elt-基数。这将给你一个索引(C风格)或数字(纯数学)的差异,这取决于你如何进行计算。
offset=数字/SIZE。如果你需要的话,这将完成任务。
i=offset/R。这里的整数除法-去掉余数。
j=偏移量-(i*R)或j=偏移%R。选择要使用的运算:multiply&减法或模数。