在C中,我必须将数组传递给单个变量中的函数,并且在程序运行之前不知道数组的大小。纸上解决方案是在数组中添加一个额外的元素,您将存储数组的大小(我认为这被称为" sentinel值")。好的,但是我在实现这个问题上遇到了问题。
将array []作为函数参数传递似乎不起作用。我想我可以发送指向第一个元素的指针,但是如何访问数组的其余部分呢?
答案 0 :(得分:1)
在C中,数组在大多数上下文中衰减为指向其第一个元素的指针:
6.3.2.1左值,数组和函数指示符
[...]除非是 sizeof 运算符的操作数,否则 _Alignof 运算符, 或者 一元 & 运算符,或者是用于初始化数组的字符串文字,一个表达式 类型''数组类型''被转换为类型为''指向类型'的指针的表达式 到数组对象的初始元素,而不是左值。如果数组对象有 注册存储类,行为未定义。
这很有用,因为数组索引a[i]
是使用指针算法定义的:*(a+i)
。
因此,您可以在指针上使用与数组相同的操作
但是,这种一致性还有一个缺点:如果没有将数据包装在struct
中,则无法按值传递数组。
接下来,sentinel
是用作停止标记的元素类型的无效值,对于字符串0和指针大多为NULL
。
你实际描述的是一个计数数组,其长度前面是索引((size_t*)a)[-1]
或其他一些。
答案 1 :(得分:1)
sentinel值的选择取决于阵列存储的数据类型。对于任何涉及指针的内容,请使用NULL
和NaN
作为浮点数,例如:
char *strings[] = {"foo", "bar", "baz", NULL};
double *doubles[] = {1.0, 2.4, 6.5, NaN};
现在检查数组结束的位置等于沿着数组行走,直到找到sentinel:
size_t get_length(char **strings) {
size_t cnt = 0;
while (*strings++)
cnt++;
return cnt;
}
size_t get_length2(double **doubles) {
...
while (!isnan(*doubles++))
...
}
对于某些数据类型(例如int
),查找标记更加困难,但您可以选择常规值。
答案 2 :(得分:-1)
迭代其地址作为第一个参数传入的数组,并按照传入的数组长度检查范围作为第二个参数。
// Or, void f(int *a, int size) as the array decays
// to a pointer when passed into this function
void f(int a[], int size)
{
// It's your own responsibility to make sure you
// don't access the out-of-range elements.
for (int i = 0; i < size; ++i)
{
printf ("%d\n", a[i]);
}
}
// use of f()
int a[10];
// or f(&a[0], sizeof(a) / sizeof(a[0]))
f(a, sizeof(a) / sizeof(a[0]));