查找函数内的数组长度

在下面的程序中,数组ar的长度在main中是正确的,但在temp它显示指向ar的指针的长度,在我的计算机上它是2(以sizeof(int)为单位)。

 #include  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; } 

我想知道如何定义函数,以便在函数中正确读取数组的长度。

没有“内置”方法来确定函数内部的长度。 但是,如果传递arrsizeof(arr)将始终返回指针大小。 因此,最好的方法是将元素的数量作为单独的参数传递。 或者你可以有一个特殊的值,如0-1 ,表示结束(就像字符串中的\0 ,只是char [] )。 但当然’逻辑’数组大小是sizeof(arr)/sizeof(int) - 1

正如其他人所说,显而易见的解决方案是将数组的长度作为参数传递,也可以将此值存储在数组的开头

 #include  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; } 

不要使用函数,为此使用宏:

 //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; } 

这需要更长的时间来设置,但如果您发现自己将其传递给许多函数,则非常有用。

当你写size(ar)然后你传递指针不是数组

指针和int的大小是4或8 – 取决于ABI (或者,提到@ H2CO3 – 完全不同),所以你得到sizeof(int *)/sizeof intsizeof(int *)/sizeof int = 1表示32位机和8/4 = 2用于64位机器),这是1或2(或者……不同的东西)。

请记住,在C中,当一个数组作为函数的参数传递时,您将传递一个指向数组的指针。
如果要传递数组的大小,则应将其作为单独的参数传递。

我不认为你可以使用一个函数来做到这一点。 它将始终返回指针的长度而不是整个数组的长度。

函数ar内部是一个指针,因此sizeof运算符将返回指针的长度。 计算它的唯一方法是使ar全局化或更改其名称。 确定长度的最简单方法是size(array_name)/(size_of(int)。您可以做的另一件事是将此计算传递给函数。

您需要将数组包装到结构中:

 #include 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; } 

2018年3月10日修订

OP的代码调用temp()并通过数组名传递一个指向int类型数据的指针,该数组名默认属于arr [0]temp()的forms参数表示指向int类型数据的指针,数组表示法指示指针与数组中的元素相关。

Per geeksforgeeks :

由于效率,数组参数被视为指针。

geeksforgeeks的另一篇文章解释说,使用带指针的sizeof表示数据类型所需的字节数,而不是数组的长度。 本文建议传递一个额外的参数:实际的数组大小。 在这种情况下,我通过对该值进行硬编码来创建一个常量,如下面的示例所示:

  #define ARR_SIZE 3 #include  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; } 

见演示

更好的选择包括传递数组的大小而不对该值进行硬编码。 @weston提供了一个很好的建议,可以编写类似函数的宏来确定数组的长度。 虽然您不能在temp()的函数体中使用宏,但您可以使用宏将数据传递给temp(),如下所示:

 #define array_len(array) sizeof(array)/sizeof(array[0]) #include  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; } 

查看实时代码

有趣的相关讨论和关于宏的良好阅读在这里 。