我怎么知道数组的末端在哪里?
如果您没有将数组的大小作为单独的参数(您应该是)传递,那么您将不得不使用某种标记值(C 字符串在字符串中的最后一个字符之后使用 0 的方式)。
我想我应该将指针传递给数组的第一个元素,因为我认为 C 不会让数组的值被传递,但有点不确定。
C 的数组语义有点棘手。除非它是sizeof
, _Alignof
, 或一元运算符的操作数&
,或者是用于在声明中初始化数组的字符串文字,否则“N-element array of T
”类型的表达式将转换为“pointer”类型的表达式到T
",表达式的值将是数组中第一个元素的地址。所以,给定代码
int arr1[10];
foo(arr1); // equivalent to foo(&arr1[0]);
arr1
调用中的表达式foo
将从“10元素数组int
”转换为“指针int
”,接收的值foo
是数组第一个元素的地址:
void foo(int *a)
{
// do stuff with a[i]
}
表达式a[i]
被解释为*(a + i)
; 我们找到后面的第i
' 个元素的地址a
并取消引用结果。
这是一种冗长的说法,您将[]
在函数的参数上使用运算符,就好像它们是常规数组一样。
将数组返回给主函数时,如何在不清理内存的情况下返回结果函数?
不太清楚你在这里的意思。请注意,以下代码将不起作用:
int *foo(int *a1, int *a2)
{
int a3[SOME_SIZE];
// copy elements from a1 and a2 to a3;
return a3;
}
一旦foo
退出,数组a3
就不存在了;该内存被系统回收,因此您返回的指针值不再有效。你有三个选择:
首先,您可以将目标数组作为第三个参数传递:
int main(void)
{
int arr1[N];
int arr2[M];
int arr3[K];
...
foo(arr1, arr2, arr3);
...
}
void foo(int *a1, int *a2, int *result) { ... }
前提是result
指向一个足够大的数组以容纳您找到的所有元素(它应该与两个源数组中较大的一个一样大)。如果您不想搞乱动态内存管理,这就是要走的路。
其次,可以在函数中动态分配目标数组:
int main(void)
{
int a1[M];
int a2[N];
int *a3;
...
a3 = foo(a1, a2);
...
free(a3);
}
int *foo(int *a1, int *a2)
{
int *result = malloc(sizeof *result * SOME_SIZE);
...
if (element_in_both_arrays())
result[n++] = element_from_both_arrays();
...
return result;
}
完成后,您必须记住释放内存。
最后,您可以将目标数组声明为全局变量(即在文件范围内)。我不打算举一个例子,因为你不想那样做。
每当您将数组传递给函数或返回动态分配的缓冲区时,您确实需要将数组大小作为单独的参数传递。通常,仅根据指针值无法确定数组中有多少元素。您可以使用标记值,但它们只告诉您数组的逻辑大小,而不是其物理大小。例如:
char buffer[1024] = "foo";
的逻辑大小buffer
为 3(字符串的长度),但其物理大小为 1 KB。