C将未知大小的数组传递给单个变量中的函数
在C中,我必须将数组传递给单个变量中的函数,并且在程序运行之前不知道数组的大小。 纸上解决方案是在数组中有一个额外的元素,你将存储数组的大小(我认为这称为“哨兵值”)。 好的,但我在实现这个问题时遇到了问题。
将array []作为函数参数传递似乎不起作用。 我想我可以发送指向第一个元素的指针,但是如何访问数组的其余部分呢?
在C中,数组在大多数上下文中衰减为指向其第一个元素的指针:
6.3.2.1左值,数组和函数指示符
[…]除非它是sizeof运算符, _Alignof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则类型为”数组’类型的表达式是转换为类型为”指向类型’的指针的表达式,指向数组对象的初始元素,而不是左值。 如果数组对象具有寄存器存储类,则行为未定义。
这很有用,因为数组索引a[i]
是使用指针算法定义的: *(a+i)
。
因此,您可以在指针上使用与数组相同的操作。
但是,这种一致性还有一个缺点:如果不将数据包装在struct
则无法按值传递数组。
接下来, sentinel
是用作停止标记的元素类型的无效值,对于字符串0和指针大多为NULL
。
你实际描述的是一个计数数组,其长度前置于索引((size_t*)a)[-1]
或其他一些。
sentinel值的选择取决于arrays存储的数据类型。 对于涉及指针的任何内容,使用NULL
和NaN
作为浮点,例如:
char *strings[] = {"foo", "bar", "baz", NULL}; double *doubles[] = {1.0, 2.4, 6.5, NaN};
现在检查数组结束的位置相当于沿arrays行走,直到找到哨兵为止:
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
),查找标记更加困难,但您可以选择常规值。
迭代其地址作为第一个参数传入的数组,并通过作为第二个参数传入的数组长度检查范围。
// 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]));