如何动态计算动态分配内存的大小
How to dynamically calculate the size of a dynamically allocated memory
考虑代码如下:
int i, a_size, s_size, n;
char **a;
a_size = 100; // examples
s_size = 10;
a = malloc(a_size * sizeof(char*));
for (int i = 0; i < a_size; i++)
a[i] = malloc((s_size) * sizeof(char));
现在,我想动态计算数组中有多少个元素(因此,忽略a_size
)。哪个是正确的方法?
通常你不能,你应该自己处理这种簿记,但一种可能性是存储一个额外的行指针设置为 NULL
(又名 哨兵):
a = malloc((a_size + 1) * sizeof(char*)); // allocate additional row pointer
for (int i = 0; i < a_size; i++) // allocate rows
a[i] = malloc(s_size);
a[a_size] = NULL; // set sentinel row to NULL
然后您可以通过遍历行指针直到找到 NULL
行来确定大小。请注意,如果您经常这样做,或者如果行数可能很大,这可能会非常低效。
首先你动态分配了 101 one-dimensional 个数组。
分配的字符总数等于乘积s_size * s_size
。
您可以使用哨兵,但通常很难 select 哨兵的值。
所以你应该自己将这些值存储在变量中。
您需要确定存储在一个 one-dimensiobal 数组中且元素类型为 char
的字符串的长度 您应该使用在 header 中声明的标准 C 函数 strlen
<string.h>
例如
strlen( a[0] )
TL;DR 指针不存储有关已分配内存大小的任何信息。因此,没有直接的 API 类东西可以用来确定分配的大小。
然而,一些动态内存分配库提供了一些选项来实际获取有关分配大小的信息,但这是非标准的并且在很大程度上依赖于实现。
就是说,您可以想出一种方法,您可以明确地标记数据的结尾(检查sentinel value概念) 存储到动态分配的内存中(因此,本质上,标记分配内存的末尾)但是,这也是您必须注意的事情。
请记住。正如 Mr. Paul R 非常正确地提到的那样,这种哨兵值方法可能效率很低,并且这种方法可能有很多限制,例如
- 不能将标记值作为 合法 值之一。
- 万一标记值没有出现在分配的最后,它可能会提供有关分配大小的错误信息。
- 你总是在分配一些未被使用的内存(放置哨兵)有效。
等等。
恕我直言,最好的方法是,在单独的变量中跟踪分配的大小,并在必要时使用指针传递它。
实现所需簿记机制的一种可能性(尽管这可能不是一个好方法)是实现自定义分配、大小和自由函数,可以用以下方式概括,其中 size_t
是用于数组大小的类型;该方法类似于 Pascal 样式字符串。
对于分配,分配更多sizeof(t_size)
内存,将其写入分配块的开头,return一个指针刚好指向第一个sizeof(t_size)
字节之后。
要获得大小,只需查看数组前的 sizeof(t_size)
个字节。
对于free函数,从存储大小的位置开始释放内存块,这是实际分配的块的开始。
考虑代码如下:
int i, a_size, s_size, n;
char **a;
a_size = 100; // examples
s_size = 10;
a = malloc(a_size * sizeof(char*));
for (int i = 0; i < a_size; i++)
a[i] = malloc((s_size) * sizeof(char));
现在,我想动态计算数组中有多少个元素(因此,忽略a_size
)。哪个是正确的方法?
通常你不能,你应该自己处理这种簿记,但一种可能性是存储一个额外的行指针设置为 NULL
(又名 哨兵):
a = malloc((a_size + 1) * sizeof(char*)); // allocate additional row pointer
for (int i = 0; i < a_size; i++) // allocate rows
a[i] = malloc(s_size);
a[a_size] = NULL; // set sentinel row to NULL
然后您可以通过遍历行指针直到找到 NULL
行来确定大小。请注意,如果您经常这样做,或者如果行数可能很大,这可能会非常低效。
首先你动态分配了 101 one-dimensional 个数组。
分配的字符总数等于乘积s_size * s_size
。
您可以使用哨兵,但通常很难 select 哨兵的值。
所以你应该自己将这些值存储在变量中。
您需要确定存储在一个 one-dimensiobal 数组中且元素类型为 char
的字符串的长度 您应该使用在 header 中声明的标准 C 函数 strlen
<string.h>
例如
strlen( a[0] )
TL;DR 指针不存储有关已分配内存大小的任何信息。因此,没有直接的 API 类东西可以用来确定分配的大小。
然而,一些动态内存分配库提供了一些选项来实际获取有关分配大小的信息,但这是非标准的并且在很大程度上依赖于实现。
就是说,您可以想出一种方法,您可以明确地标记数据的结尾(检查sentinel value概念) 存储到动态分配的内存中(因此,本质上,标记分配内存的末尾)但是,这也是您必须注意的事情。
请记住。正如 Mr. Paul R 非常正确地提到的那样,这种哨兵值方法可能效率很低,并且这种方法可能有很多限制,例如
- 不能将标记值作为 合法 值之一。
- 万一标记值没有出现在分配的最后,它可能会提供有关分配大小的错误信息。
- 你总是在分配一些未被使用的内存(放置哨兵)有效。
等等。
恕我直言,最好的方法是,在单独的变量中跟踪分配的大小,并在必要时使用指针传递它。
实现所需簿记机制的一种可能性(尽管这可能不是一个好方法)是实现自定义分配、大小和自由函数,可以用以下方式概括,其中 size_t
是用于数组大小的类型;该方法类似于 Pascal 样式字符串。
对于分配,分配更多sizeof(t_size)
内存,将其写入分配块的开头,return一个指针刚好指向第一个sizeof(t_size)
字节之后。
要获得大小,只需查看数组前的 sizeof(t_size)
个字节。
对于free函数,从存储大小的位置开始释放内存块,这是实际分配的块的开始。