我分配了一个mystructn大小的"数组",如下所示:

if (NULL == (p = calloc(sizeof(struct mystruct) * n,1))) {
 /* handle error */
}

后来,我只有p,不再有n.有没有办法只给出指针p就能确定数组的长度?

我认为这是可能的,因为free(p)就是这样.我知道malloc()会记录它分配了多少内存,这就是它知道长度的原因;也许有办法查询这些信息?比如...

int length = askMallocLibraryHowMuchMemoryWasAlloced(p) / sizeof(mystruct)

我知道我应该重新编写代码,这样我就知道n个,但如果可能的话,我宁愿不要.有什么 idea 吗?

推荐答案

不,如果不强烈依赖malloc的实现细节,就无法获得这些信息.特别是,malloc可能会分配比您请求的更多字节(例如,为了特定内存体系 struct 的效率).最好是重新设计代码,以便明确地跟踪代码.另一种方法是进行同样多的重新设计,并采用更危险的方法(考虑到它是非标准的,滥用了指针的语义,对后面的人来说将是维护的噩梦):将长度n存储在malloc的地址,然后是array.分配将是:

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);

Edit:美元只是为了扮演魔鬼的代言人.我知道这些"解决方案"都需要重新设计,但让我们来玩一玩吧. 当然,上面给出的解决方案只是一个(包装良好的) struct 的简陋实现.你不妨定义一下:

typedef struct { 
  unsigned int n;
  void *arr;
} arrInfo;

并传递大约arrInfo个指针,而不是原始指针.

现在我们在做饭.但只要你在重新设计,为什么就到此为止?您真正想要的是抽象数据类型(ADT).算法和数据 struct 类的任何介绍性文本都可以.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++为结尾.愿god 帮助我们所有人.

C++相关问答推荐

VS代码C/C++扩展intellisense无法检测环境特定函数'

为什么复合文字(C99)的返回会生成更多的汇编代码?

__VA_OPT__(,)是否可以检测后面没有任何内容的尾随逗号?

LibpCap禁用监视器模式(C、MacOS)

如何在不使用其他数组或字符串的情况下交换字符串中的两个单词?

如何在ASM中访问C struct 成员

为什么memcpy进入缓冲区和指向缓冲区的指针工作相同?

如何在下面的C代码中正确管理内存?

如何计算打印二叉搜索树时每行所需的空间?

如何使用libgpio(d)为Raspberry Pi编译C程序?

C将数组传递给函数以修改数组

Caesar密码调试:输出文本末尾的问号和随机字符

循环中的静态变量与块中的变量和循环

将数字的每一位数平方,并使用C将它们连接为一个数字(程序不能正确处理0)

C:Assignment中的链表赋值从指针目标类型中丢弃‘const’限定符

将 struct 数组写入二进制文件时发生Valgrind错误

C:面筋蛋白';为什么不刷新窗口?

挥发性语义的形式化理解

在C中打印指针本身

函数的typedef是标准 C 语法吗?它与函数指针的typedef有何不同?