当前位置:  开发笔记 > 编程语言 > 正文

如何从C中的指针获取数组的大小?

如何解决《如何从C中的指针获取数组的大小?》经验,为你挑选了4个好方法。

我已经分配了一个像这样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,但如果可能,我宁愿不这样做.有任何想法吗?



1> Barry Wark..:

不,如果不强烈依赖于实施细节,就无法获得这些信息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;

传递arrInfos而不是原始指针.

现在我们正在做饭.但只要你重新设计,为什么要停在这里?你真正想要的是一个抽象数据类型(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++.上帝帮助我们所有人.


@Joel - 曾经想过delete []*p如何设法调用p指向的数组中的所有析构函数 - 这就是coz new与bary建议的相同的东西.new将数组中项目的no存储在数组的开头,并为您提供指向第一个位置的指针.

2> Steven A. Lo..:

自己跟踪数组大小; free使用malloc链释放已分配的,该不一定与您请求的数组大小相同



3> paercebal..:

只是为了确认以前的答案:通过研究一个指针,没有办法知道返回这个指针的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语言中,你总是可以编写自己的分配器,但是,当你只需要记住分配了多少内存时,可能会遇到太麻烦.


必须将get_size传递给指向已分配块的开头的指针这一事实并非如此.只是不要传入无效的值.free()具有相同的约束,并且存在......

4> dmityugov..:

有些编译器提供了msize()或类似的函数(_msize()等),让你可以做到这一点


它在OSX上称为malloc_size.
推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有