在下面的程序中,数组ar
的长度在main中是正确的,但在temp
中它显示指向ar
的指针的长度,该指针在我的计算机上为2(以单位为单位) sizeof(int)
)。
#include <stdio.h>
void temp(int ar[]) // this could also be declared as `int *ar`
{
printf("%d\n", (int) sizeof(ar)/sizeof(int));
}
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", (int) sizeof(ar)/sizeof(int));
temp(ar);
return 0;
}
我想知道如何定义函数,以便在函数中正确读取数组的长度。
答案 0 :(得分:16)
没有“内置”方法来确定函数内部的长度。无论您传递arr
,sizeof(arr)
将始终返回指针大小。所以最好的方法是将元素的数量作为单独的参数传递。或者,您可以使用0
或-1
这样的特殊值来表示结束(就像字符串中\0
一样,只是char []
)。
但当然“逻辑”数组大小为sizeof(arr)/sizeof(int) - 1
答案 1 :(得分:9)
正如其他人所说的那样明显的解决方案是将数组的长度作为参数传递,你也可以将这个值存储在数组的开头
#include <stdio.h>
void temp(int *ar)
{
printf("%d\n", ar[-1]);
}
int main(void)
{
int ar[]= {0, 1, 2, 3};
ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
printf("%d\n", ar[0]);
temp(ar + 1);
return 0;
}
答案 2 :(得分:6)
不要使用函数,请使用宏:
//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", arrayLength(ar));
return 0;
}
您仍然无法在像temp
这样的函数中使用此宏,其中数组作为参数传递,原因是其他人提到的。
替代方法是,如果要传递一种数据类型,则定义一个同时具有数组和容量的类型:
typedef struct
{
int *values;
int capacity;
} intArray;
void temp(intArray array)
{
printf("%d\n", array.capacity);
}
int main(void)
{
int ar[]= {1, 2, 3};
intArray arr;
arr.values = ar;
arr.capacity = arrayLength(ar);
temp(arr);
return 0;
}
这需要更长的时间来设置,但如果您发现自己将其传递给许多函数,则非常有用。
答案 3 :(得分:4)
当你写size(ar)
时,你传递的是指针和而不是数组。
指针和int的大小是4或8 - 取决于 ABI (或者,如提到的@ H2CO3 - 完全不同的东西),所以你得到sizeof(int *)/sizeof int
(对于32位计算机,4/4 = 1,对于64位计算机,8/4 = 2),这是1或2(或者......不同的东西)。
请记住,在C中,当一个数组作为函数的参数传递时,你将一个指针传递给一个数组。
如果你想传递数组的大小,你应该将它作为一个分开的传递参数。
答案 4 :(得分:1)
我认为你不能使用函数来做到这一点。它总是返回指针的长度而不是整个数组的长度。
答案 5 :(得分:0)
函数ar内部是一个指针,因此sizeof运算符将返回指针的长度。计算它的唯一方法是使ar全局化或更改其名称。确定长度的最简单方法是size(array_name)/(size_of(int)。您可以做的另一件事是将此计算传递给函数。
答案 6 :(得分:0)
您需要将数组包装到结构中:
#include<stdio.h>
struct foo {int arr[5];};
struct bar {double arr[10];};
void temp(struct foo f, struct bar g)
{
printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}
void main(void)
{
struct foo tmp1 = {{1,2,3,4,5}};
struct bar tmp2;
temp(tmp1,tmp2);
return;
}
答案 7 :(得分:-2)
2018年3月10日修订:
OP的代码调用temp()并通过数组名传递一个指向int类型数据的指针,该数组名默认属于 arr [0] 。 temp()的形式参数表示指向int类型数据的指针,其中数组表示法指示指针与数组中的元素相关。
由于效率,数组参数[被]被视为指针。
geeksforgeeks的另一篇文章解释说,将 sizeof 与指针一起使用表示数据类型所需的字节数,而不是数组的长度。本文建议传递一个额外的参数:实际的数组大小。在这种情况下,我通过对该值进行硬编码来创建一个常量,如下面的示例所示:
#define ARR_SIZE 3
#include <stdio.h>
void temp(int arr[], size_t arr_size)
{
int i;
puts ("In temp:");
for (i = 0; i <= arr_size - 1; i++)
{
printf(" %d",arr[i]);
}
puts("\nExiting temp...\n");
}
int main(void)
{
int ar[ARR_SIZE]={1,2,3};
int i=0;
temp(ar,ARR_SIZE);
puts("In main():");
for(i = 0; i < sizeof(ar)/sizeof(ar[i]); i++)
printf(" %d ", ar[i]);
return 0;
}
请参阅demo
更好的选择包括传递数组的大小而不对该值进行硬编码。 @weston提供了一个很好的建议,可以编写类似函数的宏来确定数组的长度。虽然您不能在temp()的函数体中使用宏,但您可以使用宏将数据传递给temp(),如下所示:
#define array_len(array) sizeof(array)/sizeof(array[0])
#include <stdio.h>
void temp(int arr[], size_t arr_size)
{
int i;
printf("\nArray size is: %d\nValues are:\n", (int) arr_size);
for (i = 0; i <= arr_size - 1; i++)
{
printf(" %d",arr[i]);
}
}
int main(void)
{
int ar[]={1,2,3};
int i=0;
temp( ar, array_len(ar) );
return 0;
}
请参阅live code
有趣的相关discussion以及关于宏here的好读物。