假设我有一个包含16个元素的双数组double myArray[16]
。我想对四个元素的每个子集执行一个函数,即第一个子集是myArray[0], myArray[1], myArray[2], myArray[3]
,第二个子集是myArray[4], myArray[5], myArray[6], myArray[7]
,依此类推。
我想使用指向仅在子集上运行的void
函数的指针传递子集数组,并将值写入传递给函数的地址。如果我想使用以myArray[8]
开头的所有元素,我可以将&myArray[8]
传递给函数,但是我只需要传递一个预定长度(本例中为4)。
感谢任何帮助!
答案 0 :(得分:0)
为了让函数知道传递数组的长度,数组需要在单独的内存中携带此信息。这是一个开销,C是为零开销而设计的,所以它不支持这个。
有些语言会自动传递此信息(因此,它们会变慢)。
您唯一的选择是硬编码您想要在函数中使用的数组的大小(这可能是正常的,或者非常适合您的情况,具体取决于您的上下文),或者将其作为附加参数传递。 / p>
答案 1 :(得分:0)
是否要使用array[16]
,就好像它是array[4][4]
?
您可以使用union
:
#include <stdio.h>
union set {
double arr[16];
double sub[4][4];
};
static void func(void *data) /* Why not double *? */
{
double *x = data;
int i;
for (i = 0; i < 4; i++) {
printf("%f\n", *x++);
}
}
int main(void)
{
union set x = {.arr = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.}};
int i;
for (i = 0; i < 4; i++) {
func(&x.sub[i]);
}
return 0;
}
答案 2 :(得分:0)
只需通过预定的长度
在C中,数组是连续的。要对元素0,1,2,3进行操作,该函数只需要接收元素0的地址。要对元素8,9,10,11进行操作,该函数只需要接收元素8的地址。所以代码不能传递一个数组的长度,但是传递数组子集的基地址。
#define N 16
#define DELTA 4
void fun(int base, double *a) {
for (int i=0; i<N; i++) {
printf("%2d %e\n", base + i, a[i]);
}
}
double myArray[N];
assert(N%DELTA == 0);
for (int i=0 i<N; i += DELTA) {
fun(i, &myArray[i]);
}
答案 3 :(得分:0)
即使你有一个函数void myFunction(double arr[4])
,C编译器也会将它视为`void myFunctoin(double * arr)。数组本身没有按值传递;只传入指针值,并使用指针算术和解除引用来引用数组元素。
在C中,指针与数组之间几乎没有区别。您不能分配给数组,但可以分配给指针。除此之外,它们几乎可以互换。
int array[10];
int *ptr = &array[0];
// All 4 of these do the same thing
array[3] = 5;
*(array + 3) = 5;
ptr[3] = 5;
*(ptr + 3) = 5;
// all 4 of these do the same thing too
functionCall(&array[3]);
functionCall(array + 3);
functionCall(&ptr[3]);
functionCall(ptr + 3);
// this is pretty much the only thing different
printf("sizeof(array)=%d\n", sizeof(array)); // prints sizeof(int)*10
printf("sizeof(ptr)=%d\n", sizeof(ptr)); // prints sizeof(int *)
// and this
ptr = array + 5; // fine
array = array + 5; // will not compile, since you can't assign to arrays.
答案 4 :(得分:0)
在C中,您需要在编译时设置数组的大小。当你动态改变数组的长度时,它真的不喜欢。编译程序时应该得到一个例外。对于这种情况,您将使用指向内存中连续空间的指针,并且每次添加或删除数组中的任何内容时都会使用realloc,因此它始终是连续的并且可以轻松搜索。
但是,您正在使用数组,因此我们在编译时返回到定义的大小。由于您在编译时知道大小,因此您应该能够将数组拆分为四个或更多个部分。如果将16除以你需要的多个子集并取走1(结果需要为此工作),你可以通过0代表0-3,1代表4-7,2代表8-11来寻址子集和12-16的3。在代码中它看起来像这样
void funciton(int array[16], int subset) {
int i = 0;
for(i = 0;i < 4;i++) {
array[(subset * 4) + i] = foobar;
}
}