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位系统上为四个字节)?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位系统上为四个字节)?sizeof()
的方法。size_t
的块,将大小存储在其中,并将ptr+sizeof(size_t)
作为数组的指针返回。当你需要大小时,将指针减小并查看存储的值。只需记住从开头释放整个块,而不仅仅是数组部分。答案是,“不”。
C语言程序员的做法是在某个地方存储数组的大小。它可以是结构体的一部分,或者程序员可以有些取巧地使用malloc()
比所请求的内存多来存储一个长度值,以便在数组开始之前存储它。
对于动态数组(使用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,它更安全、更易于使用。
ARRAY_SIZE
宏的参数是一个数组(即数组类型的表达式),那么它总是有效的。对于所谓的“动态数组”,您永远不会得到实际的“数组”(即数组类型的表达式)。 (当然,您不能,因为数组类型在编译时包括其大小。)您只会得到指向第一个元素的指针。您的反对意见“没有检查参数是否真的是静态数组”并不真正有效,因为它们是不同的,一个是数组,另一个则不是。 - newacctsizeof
。下面的getSize()
函数返回任何静态数组的大小。#include <cstddef>
template<typename T, std::size_t SIZE>
constexpr std::size_t getSize(T (&)[SIZE]) {
return SIZE;
}
#include <cstddef>
#include <cstdio>
template<typename T, std::size_t SIZE>
constexpr std::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}};
std::printf("%u\n", getSize(foos3));
std::printf("%u\n", getSize(foos5));
}
输出:
3
5
T (&)[SIZE]
。你能解释一下它的含义吗?此外,您还可以在此上下文中提到constexpr。 - WorldSEnderSIZE
作为参数传递,它是一个模板参数,必须已经被函数定义知道。) - Peter Cordes#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 */
int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 };
int *ptr = days + 1;
printf("array length: %u\n", ptr[-1]);
return 0;
对于这个具体的例子,如果您使用typedefs(请参见下文),是有办法的。当然,如果您以这种方式做,最好使用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;
}
输出:
SIZEOF_DAYS: 20
sizeof(days): 20
sizeof(*ptr): 20
sizeof(ptr): 4
没有什么神奇的解决方案。C语言不具备反射性,对象不能自动知道它们是什么。
但你有很多选择:
我的解决方案是将数组的长度保存到一个叫做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;
}
但您需要关注设置要存储的数组的正确长度,因为没有办法检查此长度,就像我们的朋友们所解释的那样。
typedef struct intArr {
int size;
int* arr;
} intArr_t;
int main() {
intArr_t arr;
arr.size = 6;
arr.arr = (int*)malloc(sizeof(int) * arr.size);
for (size_t i = 0; i < arr.size; i++) {
arr.arr[i] = i * 10;
}
return 0;
}
size_t
存储大小。 - David RanieriintArr
。另外,更短更易读的写法是 arr.arr = malloc(arr.size * sizeof *arr.arr);
,这样更具可重用性,因为你不需要指定“int”。 - Amarok24