首先,这里有一些代码:
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个字节)?
首先,这里有一些代码:
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个字节)?
当前回答
正如所有正确答案所述,您不能仅从数组的衰减指针值获得此信息。如果衰减指针是函数接收到的参数,则必须以其他方式提供原始数组的大小,以便函数知道该大小。
这里有一个不同于目前所提供的建议,它可以工作:传递一个指向数组的指针。这个建议类似于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 */
如果假定函数能够操作任意大小的数组,则必须将大小作为附加信息提供给函数。
其他回答
有一个流行的宏,你可以定义它来查找数组中的元素数量(Microsoft CRT甚至为它提供了名为_countof的OOB):
#define countof(x) (sizeof(x)/sizeof((x)[0]))
然后你可以这样写:
int my_array[] = { ... some elements ... };
printf("%zu", countof(my_array)); // 'z' is correct type specifier for size_t
我对这个问题的解决方案是将数组的长度保存到一个struct array中,作为关于数组的元信息。
#include <stdio.h>
#include <stdlib.h>
struct Array
{
int length;
double *array;
};
typedef struct Array Array;
Array* NewArray(int length)
{
/* Allocate the memory for the struct Array */
Array *newArray = (Array*) malloc(sizeof(Array));
/* Insert only non-negative length's*/
newArray->length = (length > 0) ? length : 0;
newArray->array = (double*) malloc(length*sizeof(double));
return newArray;
}
void SetArray(Array *structure,int length,double* array)
{
structure->length = length;
structure->array = array;
}
void PrintArray(Array *structure)
{
if(structure->length > 0)
{
int i;
printf("length: %d\n", structure->length);
for (i = 0; i < structure->length; i++)
printf("%g\n", structure->array[i]);
}
else
printf("Empty Array. Length 0\n");
}
int main()
{
int i;
Array *negativeTest, *days = NewArray(5);
double moreDays[] = {1,2,3,4,5,6,7,8,9,10};
for (i = 0; i < days->length; i++)
days->array[i] = i+1;
PrintArray(days);
SetArray(days,10,moreDays);
PrintArray(days);
negativeTest = NewArray(-5);
PrintArray(negativeTest);
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 */
如果假定函数能够操作任意大小的数组,则必须将大小作为附加信息提供给函数。
不,你不能。编译器不知道指针指向什么。有一些技巧,比如用一个已知的带外值结束数组,然后计算数组的大小直到该值为止,但这不是使用sizeof()。
另一个技巧是Zan提到的,那就是把大小藏在某个地方。例如,如果你在动态分配数组,分配一个比你需要的大一个整型的块,在第一个整型中保存大小,并返回ptr+1作为指向数组的指针。当您需要指针的大小时,可以递减指针并查看存储的值。记住要从头开始释放整个块,而不仅仅是数组。
没有神奇的解决办法。C不是一种反射语言。对象不会自动知道它们是什么。
但你有很多选择:
显然,要添加一个参数 将调用包装在宏中并自动添加参数 使用更复杂的对象。定义一个包含动态数组和数组大小的结构。然后,传递结构的地址。