我已经分配了一个像这样mystruct
大小的"数组" n
:
if (NULL == (p = calloc(sizeof(struct mystruct) * n,1))) { /* handle error */ }
后来,我只能访问p
,不再拥有n
.有没有办法只给出指针确定数组的长度p
?
我认为它必须是可能的,因为free(p)
就是这样.我知道malloc()
它记录了它分配了多少内存,这就是它知道长度的原因; 也许有办法查询这些信息?就像是...
int length = askMallocLibraryHowMuchMemoryWasAlloced(p) / sizeof(mystruct)
我知道我应该修改代码,以便我知道n
,但如果可能,我宁愿不这样做.有任何想法吗?
不,如果不强烈依赖于实施细节,就无法获得这些信息malloc
.特别是,malloc
可以分配比您请求更多的字节(例如,为了特定存储器架构中的效率).重新设计代码会更好,以便您n
明确地跟踪.替代方案至少是重新设计和更危险的方法(鉴于它是非标准的,滥用指针的语义,对于那些n
追随你的人来说将是一个维护噩梦):将长度保存在malloc'd地址,后跟数组.分配将是:
void *p = calloc(sizeof(struct mystruct) * n + sizeof(unsigned long int),1)); *((unsigned long int*)p) = n;
n
现在存储在*((unsigned long int*)p)
数组中,现在是数组的开头
void *arr = p+sizeof(unsigned long int);
编辑:只是为了扮演魔鬼的拥护者......我知道这些"解决方案"都需要重新设计,但让我们来解决它.当然,上面介绍的解决方案只是一个(包装好的)结构的hacky实现.你不妨定义:
typedef struct { unsigned int n; void *arr; } arrInfo;
传递arrInfo
s而不是原始指针.
现在我们正在做饭.但只要你重新设计,为什么要停在这里?你真正想要的是一个抽象数据类型(ADT).任何算法和数据结构类的介绍性文本都可以.ADT定义数据类型的公共接口,但隐藏该数据类型的实现.因此,公开的阵列的ADT可能看起来像
typedef void* arrayInfo; (arrayInfo)newArrayInfo(unsignd int n, unsigned int itemSize); (void)deleteArrayInfo(arrayInfo); (unsigned int)arrayLength(arrayInfo); (void*)arrayPtr(arrayInfo); ...
换句话说,ADT是数据和行为封装的一种形式......换句话说,它与使用直接C的面向对象编程一样接近.除非你被困在没有的平台上有一个C++编译器,你也可以全力以赴,只使用STL std::vector
.
在那里,我们采用了一个关于C的简单问题,最终得到了C++.上帝帮助我们所有人.
自己跟踪数组大小; free使用malloc链释放已分配的块,该块不一定与您请求的数组大小相同
只是为了确认以前的答案:通过研究一个指针,没有办法知道返回这个指针的malloc分配了多少内存.
这是不可能的原因之一.让我们假设一个带有假设函数的代码叫做get_size(void*),它返回为指针分配的内存:
typedef struct MyStructTag { /* etc. */ } MyStruct ; void doSomething(MyStruct * p) { /* well... extract the memory allocated? */ size_t i = get_size(p) ; initializeMyStructArray(p, i) ; } void doSomethingElse() { MyStruct * s = malloc(sizeof(MyStruct) * 10) ; /* Allocate 10 items */ doSomething(s) ; }
但是这种方法的问题在于,在C中,你可以使用指针算术.让我们重写doSomethingElse():
void doSomethingElse() { MyStruct * s = malloc(sizeof(MyStruct) * 10) ; /* Allocate 10 items */ MyStruct * s2 = s + 5 ; /* s2 points to the 5th item */ doSomething(s2) ; /* Oops */ }
get_size如何工作,因为你向函数发送了一个有效的指针,但不是malloc返回的指针.即使get_size经历了查找大小的所有麻烦(即以低效的方式),在这种情况下,它将返回一个在您的上下文中可能出错的值.
总有办法避免这个问题,而在C语言中,你总是可以编写自己的分配器,但是,当你只需要记住分配了多少内存时,可能会遇到太麻烦.
有些编译器提供了msize()或类似的函数(_msize()等),让你可以做到这一点