在下面的程序中,数组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;
}


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

评论

最好的方法是添加一个额外的参数,该参数采用数组的大小,即void temp(int * ar,size_t len);

据我了解,@ Th3Cuber他希望长度作为结果。

因为sizeof操作员计算机的大小在编译时是这样,所以它不能是动态的。您必须明确地传递它。在这里阅读:sizeof是一个编译时运算符

strlen()仅适用于字符串,不适用于整数数组,这不正确吗?

@Ishmeet strlen计算\ 0之前的字符数,而不是数组的容量。

#1 楼

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

评论


这是一个有趣的建议!我将尝试这样做。在我的程序中,数组中的值必须为正,因此我将添加负值。但是问题是这样的:如何在不知道数组中有多少元素的情况下,如何在数组末尾添加负值?

–makhlaghi
13年7月11日在9:59

在您的示例中,您将声明int ar [] = {1,2,3,-1};。在更复杂的情况下,您可以在填充之前,使用-1在循环中初始化完整的数组。

– Ingo Leonhardt
13年7月11日10:00



'逻辑'数组大小为sizeof(arr)/ sizeof(int)-1 NO数组大小为:sizeof(arr)/ sizeof(int),将-1用作最高索引。

–吉列什·乔汉(Grijesh Chauhan)
13年7月11日在10:06

@Grijesh这就是为什么我写“逻辑”的原因。考虑一下strlen(),其中也不计算“ \ 0”。

– Ingo Leonhardt
13年7月11日在10:08

#2 楼

不要使用函数,请使用宏:

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


这需要花费较长的时间设置,但是如果您发现自己将其传递给许多功能,则很有用。

评论


谢谢,但是该宏也无法在该函数中使用。如果我希望在main()中完成此工作,那么从一开始就没有问题。

–makhlaghi
13年7月11日在10:07

@astroboy很公平,我也提出了另一个建议。

–weston
13年7月11日在10:24

这是一个有趣的方法。我一定会考虑的。再次感谢。

–makhlaghi
13年7月11日在10:27

#3 楼

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

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


#4 楼

当您编写size(ar)时,您传递的是指针而不是数组。

指针和一个int的大小为4或8-取决于ABI(或者,如@ H2CO3所述-完全不同),因此您得到的是sizeof(int *)/sizeof int(对于4/4 = 1 32位计算机,对于64位计算机,则为8/4 = 2),该值是1或2(或其他值)。

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

评论


谢谢你的解释。我知道,我只是想看看在不添加参数的情况下,是否真的无法在函数内部执行此操作。

–makhlaghi
13年7月11日在10:01



@Maroun Maroun我首先写了相同的答案,但由于没有答案,因此删除了,请阅读我对问题的评论。

–吉列什·乔汉(Grijesh Chauhan)
13年7月11日在10:03

“指针和一个int的大小为4或8”-或完全不同。无需做出错误的假设就可以很好地解释这一点。

–user529758
13年7月11日在10:27

@ H2CO3可以说您可以有两个不同的值来阐明我的观点,这足够了,但是,我将添加它,这样会更好。

– Maroun
13年7月11日在10:31

“您正在将指针传递给数组。”不太正确。如果将数组传递给函数,则它“衰减”到指向其第一个元素的指针。按地址,这与指向数组的指针相同,按类型,它肯定不是。

–alk
17年12月30日在17:43

#5 楼

我认为您无法使用函数来执行此操作。它总是返回指针的长度,而不是整个数组的长度。

#6 楼

您需要将数组包装成一个结构:

#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 楼

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