C对数组的处理与Java 非常不同,因此您必须相应地调整自己的想法。C语言中的数组不是一流的对象(也就是说,在大多数情况下,数组表达式都不会保留其“数组性质”)。在C语言中,“ N个元素数组T
” 类型的表达式将隐式转换(“衰变”)为“指针指向T
” 类型的表达式,除非该数组表达式是the sizeof
或unary运算&
符的操作数,或者数组表达式是一个字符串文字,用于初始化声明中的另一个数组。
除其他外,这意味着您不能将数组表达式传递给函数并将其作为数组类型接收;该函数实际上收到一个指针类型:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
在对的调用中foo
,表达式str
从类型转换char [6]
为char *
,这就是为什么foo
声明的第一个参数char *a
而不是的原因char a[6]
。在中sizeof str
,由于数组表达式是运算sizeof
符的操作数,因此它不会转换为指针类型,因此您可以获取数组中的字节数(6)。
如果您真的有兴趣,可以阅读Dennis Ritchie的《 C语言的发展》以了解这种处理方法的来源。
结果是函数不能返回数组类型,这很好,因为数组表达式也不能成为赋值的目标。
对于调用者而言,最安全的方法是定义数组,并将其地址和大小传递给应该写入该函数的函数:
void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
...
dstArray[i] = some_value_derived_from(srcArray[i]);
...
}
int main(void)
{
char src[] = "This is a test";
char dst[sizeof src];
...
returnArray(src, sizeof src, dst, sizeof dst);
...
}
该函数的另一种方法是动态分配数组并返回指针和大小:
char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
char *dstArray = malloc(srcSize);
if (dstArray)
{
*dstSize = srcSize;
...
}
return dstArray;
}
int main(void)
{
char src[] = "This is a test";
char *dst;
size_t dstSize;
dst = returnArray(src, sizeof src, &dstSize);
...
free(dst);
...
}
在这种情况下,调用者负责使用free
库函数取消分配数组。
请注意,dst
上面的代码是指向的简单指针char
,而不是指向的数组的指针char
。C的指针和数组语义使您可以将下标运算符[]
应用于数组类型或指针类型的表达式;既src[i]
与dst[i]
将访问i
“阵列的第i个元素(即使仅src
具有阵列型)。
您可以声明一个指向的N元素数组的指针,T
并执行类似的操作:
char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
if (dstArr)
{
...
(*dstArr)[i] = ...;
...
}
return dstArr;
}
int main(void)
{
char src[] = "This is a test";
char (*dst)[SOME_SIZE];
...
dst = returnArray(src, sizeof src);
...
printf("%c", (*dst)[j]);
...
}
上面的几个缺点。首先,较早版本的C期望SOME_SIZE
是一个编译时常量,这意味着该函数将只能使用一个数组大小。其次,您必须在应用下标之前取消引用指针,这会使代码混乱。当您处理多维数组时,指向数组的指针会更好地工作。