首先,这里有一些代码:

int main() 
{
    int days[] = {1,2,3,4,5};
    int *ptr = days;
    printf("%u\n", sizeof(days));
    printf("%u\n", sizeof(ptr));

    return 0;
}

是否有一种方法可以找出ptr指向的数组的大小(而不是仅仅给出它的大小,这在32位系统上是4个字节)?


当前回答

大多数实现都有一个函数,告诉你使用malloc()或calloc()分配的对象的保留大小,例如GNU有malloc_usable_size()

但是,这将返回反转块的大小,它可以大于malloc()/realloc()的值。


其他回答

对于动态数组(malloc或c++ new),你需要像其他人提到的那样存储数组的大小,或者构建一个数组管理器结构来处理添加、删除、计数等。不幸的是,C在这方面做得不如c++好,因为你基本上必须为你存储的每一种不同的数组类型构建它,如果你需要管理多种类型的数组,这是很麻烦的。

对于静态数组(例如您示例中的数组),有一个通用宏用于获取大小,但不建议使用它,因为它不会检查参数是否真的是静态数组。宏在实际代码中使用,例如在Linux内核头文件中,尽管它可能与下面的略有不同:

#if !defined(ARRAY_SIZE)
    #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
#endif

int main()
{
    int days[] = {1,2,3,4,5};
    int *ptr = days;
    printf("%u\n", ARRAY_SIZE(days));
    printf("%u\n", sizeof(ptr));
    return 0;
}

您可以使用谷歌来提防这样的宏。小心些而已。

如果可能的话,c++的标准库,如vector,更安全,更容易使用。

大多数实现都有一个函数,告诉你使用malloc()或calloc()分配的对象的保留大小,例如GNU有malloc_usable_size()

但是,这将返回反转块的大小,它可以大于malloc()/realloc()的值。


答案是,“不。”

C程序员所做的就是将数组的大小存储在某个地方。它可以是结构的一部分,或者程序员可以欺骗一点,malloc()比要求的更多的内存,以便在数组开始之前存储长度值。

你可以这样做:

int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 };
int *ptr = days + 1;
printf("array length: %u\n", ptr[-1]);
return 0;

正如所有正确答案所述,您不能仅从数组的衰减指针值获得此信息。如果衰减指针是函数接收到的参数,则必须以其他方式提供原始数组的大小,以便函数知道该大小。

这里有一个不同于目前所提供的建议,它可以工作:传递一个指向数组的指针。这个建议类似于c++风格的建议,除了C不支持模板或引用:

#define ARRAY_SZ 10

void foo (int (*arr)[ARRAY_SZ]) {
    printf("%u\n", (unsigned)sizeof(*arr)/sizeof(**arr));
}

但是,这个建议对于您的问题来说有点愚蠢,因为函数被定义为确切地知道传入的数组的大小(因此,几乎不需要对数组使用sizeof)。不过,它所做的是提供一些类型安全性。它将禁止传入一个不需要的大小的数组。

int x[20];
int y[10];
foo(&x); /* error */
foo(&y); /* ok */

如果假定函数能够操作任意大小的数组,则必须将大小作为附加信息提供给函数。