我想将一个数组作为参数传递给另一个函数:
int i;
int main()
{
int a[5] = {1, 2, 3, 4, 5};
printf("Main:\n");
for(i=0; i<sizeof(a)/sizeof(int); i++)
{
printf("%i\n", a[i]);
}
func(a);
return;
}
void func(int a[])
{
printf("Func:\n");
for(i=0; i<sizeof(a)/sizeof(int); i++)
{
printf("%i\n", a[i]);
}
}
main
函数中的循环打印所有5个值:
Main:
1
2
3
4
5
但是函数func
中的循环只打印2个值:
Func:
1
2
为什么会出现这种奇怪的行为?
答案 0 :(得分:3)
我想将一个数组作为参数传递给另一个函数:
这是一个常见的陷阱。 阵列不会带来长度,就像在其他语言中一样。 C“数组”只是一堆连续的值,因此sizeof
不会(必然)返回数组的长度。
实际发生的是该函数将指针传递给存储数组的内存区域(因此,传递给数组的第一个元素),但没有关于该区域的信息尺寸。要“传递一个大小的数组”,你必须做一些事情来提供额外的信息:
明确传递也作为额外参数的长度。更安全:您可以传递未初始化的数组。
在数组上使用特殊的“终止”值。更紧凑:您只传递一个参数,即指向数组的指针。
(由@ CisNOTthatGOODbutISOisTHATBAD的评论隐式建议):传递指向struct
的指针,该指针包含指向内存的指针和元素(或字节)中的size_t
长度。这样做的好处是可以存储更多关于数组的元数据。
对于整数类型的数组,您甚至可以将长度存储在数组的第一个(第零个)元素中。当从具有“测量”数组和从1开始的索引的语言移植时,这有时会很有用。在所有其他情况下,请转到方法#1。 更快,更安全,在我看来更清晰。
字符串是使用方法#2的变体的字符数组:它们以特殊值(零)终止。
使用方法#1,您的功能将变为:
void func(size_t n, int a[])
{
printf("Func:\n");
for (i=0; i < n; i++)
{
printf("%i\n", a[i]);
}
}
(相当于void func(size_t n, int *a)
)。
答案 1 :(得分:2)
使用数组类型的参数声明一个函数相当于使用指针类型的参数声明它,即您的函数等效于:
void func(int *a)
因此,sizeof(a)
内func
的计算会计算int *
的大小,而不是原始数组的大小(5 * sizeof(int)
)。
由于平台上int *
的大小明显是int
大小的两倍,因此您会看到函数内部打印了两个值,而外部打印的值为五({{1}正确计算数组的大小。)
这一切都与以下事实有关:当你将一个数组传递给一个函数时,你实际在做的是将一个指针传递给它的第一个元素。
请注意,这是comp.lang.c新闻组的常见问题解答:
http://c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=aryptr#aryparmsize
答案 2 :(得分:0)
我会将代码更改为:
int i;
const int N = 5;
int main()
{
int a[N] = {1, 2, 3, 4, 5};
printf("Main:\n");
for(i=0; i<N; i++)
{
printf("%i\n", a[i]);
}
func(a);
return;
}
void func(int a[])
{
printf("Func:\n");
for(i=0; i<N; i++)
{
printf("%i\n", a[i]);
}
}
参数N是常量并定义数组的大小。 我认为这是更好的方法,然后是2个参数。