jki*_*idv 288 c arrays pointers sizeof
首先,这里是一些代码:
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有没有办法找出ptr指向的数组的大小(而不是仅仅给出它的大小,在32位系统上是4个字节)?
Pau*_*lin 250
不,你不能.编译器不知道指针指向的是什么.有一些技巧,比如以已知的带外值结束数组,然后计算大小直到该值,但这不是使用sizeof.
另一个技巧是Zan提到的那个,就是在某个地方存放大小.例如,如果您正在动态分配数组,请分配一个大于您需要的块的块,在第一个int中存储大小,并返回ptr + 1作为指向数组的指针.当您需要大小时,递减指针并查看隐藏值.只记得从头开始释放整个块,而不仅仅是数组.
Zan*_*ynx 78
答案是不."
C程序员做的是在某处存储数组的大小.它可以是结构的一部分,或者程序员可以欺骗一点和malloc()更多的内存而不是请求,以便在数组开始之前存储长度值.
Rya*_*yan 45
对于动态数组(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;
}
Run Code Online (Sandbox Code Playgroud)
你可以google出于对这类宏的警惕.小心.
如果可能的话,C++ stdlib如vector,它更安全,更易于使用.
sku*_*ton 18
有一个使用C++模板的干净解决方案,不使用sizeof().以下getSize()函数返回任何静态数组的大小:
#include <cstddef>
template<typename T, size_t SIZE>
size_t getSize(T (&)[SIZE]) {
return SIZE;
}
Run Code Online (Sandbox Code Playgroud)
这是一个foo_t结构的示例:
#include <cstddef>
template<typename T, size_t SIZE>
size_t getSize(T (&)[SIZE]) {
return SIZE;
}
struct foo_t {
int ball;
};
int main()
{
foo_t foos3[] = {{1},{2},{3}};
foo_t foos5[] = {{1},{2},{3},{4},{5}};
printf("%u\n", getSize(foos3));
printf("%u\n", getSize(foos5));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
3
5
Run Code Online (Sandbox Code Playgroud)
正如所有正确答案所述,您无法仅从数组的衰减指针值中获取此信息。如果衰减的指针是函数接收的参数,则必须以其他方式提供原始数组的大小,以便函数知道该大小。
这是一个与迄今为止提供的建议不同的建议,它会起作用:改为传递指向数组的指针。此建议类似于 C++ 样式建议,只是 C 不支持模板或引用:
#define ARRAY_SZ 10
void foo (int (*arr)[ARRAY_SZ]) {
printf("%u\n", (unsigned)sizeof(*arr)/sizeof(**arr));
}
Run Code Online (Sandbox Code Playgroud)
但是,这个建议对于您的问题来说有点愚蠢,因为函数被定义为确切知道传入的数组的大小(因此,几乎不需要在数组上使用 sizeof )。但是,它所做的是提供某种类型安全性。它会禁止您传入不需要大小的数组。
int x[20];
int y[10];
foo(&x); /* error */
foo(&y); /* ok */
Run Code Online (Sandbox Code Playgroud)
如果函数应该能够对任何大小的数组进行操作,那么您必须将大小作为附加信息提供给函数。
小智 6
你可以这样做:
int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 };
int *ptr = days + 1;
printf("array length: %u\n", ptr[-1]);
return 0;
Run Code Online (Sandbox Code Playgroud)
小智 5
对于这个具体的例子,是的,如果你使用typedef(见下文).当然,如果你这样做,你也可以使用SIZEOF_DAYS,因为你知道指针指向的是什么.
如果你有一个(void*)指针,就像malloc()等返回的那样,那么,不,没有办法确定指针所指向的数据结构,因此无法确定其大小.
#include <stdio.h>
#define NUM_DAYS 5
typedef int days_t[ NUM_DAYS ];
#define SIZEOF_DAYS ( sizeof( days_t ) )
int main() {
days_t days;
days_t *ptr = &days;
printf( "SIZEOF_DAYS: %u\n", SIZEOF_DAYS );
printf( "sizeof(days): %u\n", sizeof(days) );
printf( "sizeof(*ptr): %u\n", sizeof(*ptr) );
printf( "sizeof(ptr): %u\n", sizeof(ptr) );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
SIZEOF_DAYS: 20
sizeof(days): 20
sizeof(*ptr): 20
sizeof(ptr): 4
Run Code Online (Sandbox Code Playgroud)
没有神奇的解决方案。C 不是反射式语言。对象不会自动知道它们是什么。
但是你有很多选择: