查找动态分配数组的大小

Find the size of a dynamically allocated array

假设我们有一个这样初始化的字符串数组:

char **a = malloc(3 * sizeof(char*)); //edited

a[0]="asd";
a[1]="fghj";
a[2]="klzxc";

我们如何打印此二维数组 (3) 的第一个维度?

How can we print the first dimension of this 2D array (3)?


前面几点:

准确地说char **a不是二维数组,它是指向char的指针。

使用此内存分配的更安全方法是使用解除引用的指针而不是类型,此方法有助于代码的维护:

char **a = malloc(sizeof *a * 3);

另一件需要注意的事情是,分配给这些指针的字符串文字是只读的,不能更改。


回答你的问题:

要知道第一个维度,赋值指针的个数,需要记在心里,可能要存起来,没有可移植的方法来检索的个数你在事后分配的指针。

但是,有 non-portable 方法可以做到这一点:

size_t size = _msize(a)/sizeof *a;  //Windows

size_t size = malloc_usable_size(a)/sizeof *a; //Linux

size_t size = malloc_size(a)/sizeof *a; //Mac OS

作为函数 return 分配的字节数,将它们的 return 值除以指针的大小得到实际的指针数。


如果您需要实际的可编辑字符数组:

如果您想拥有一个可以实际编辑和更改的字符数组,您还必须为这三个指针中的每一个分配内存。

例如

for(int i = 0; i < 3; i++)
    a[i] = malloc(4) //for char arrays of 3 chars + null byte

在此之后,要分配一个字符串,您需要使用 strcpy 之类的东西,或者最好使用 memcpy.

例如

memcpy(a[0], "asd", 4); //copies "asd" to a[0]

How can we print the first dimension of this 2d array (3)?

您必须跟踪在单独变量中分配的元素数量:

size_t num_elements = 3;
char **a = malloc( sizeof *a * num_elements );
if ( a )
{
  a[0] = "asd";    // NOTE: these lines store the addresses of the string
  a[1] = "fghj";   // literals in a[0], a[1], and a[2] - you are not copying
  a[2] = "klzxc";  // the *contents* of each string, just its address
}
...
for ( size_t i; i < num_elements; i++ )
  printf( "a[%zu] = %s\n", i, a[i] );

一个指针,无论类型如何,都指向(存储地址)一个单个对象。该单个对象可能是更大的对象序列中的第一个,但无法从指针值本身确定它。如果您有以下条件:

  char **    char *            char
  +---+      +---+             +---+---+---+---+
a:|   | ---> |   | a[0] -----> |'a'|'s'|'d'| 0 |
  +---+      +---+             +---+---+---+---+
             |   | a[1] ---+
             +---+         |   +---+---+---+---+---+
             |   | a[2] -+ +-> |'f'|'g'|'h'|'j'| 0 |
             +---+       |     +---+---+---+---+---+
                         |
                         |     +---+---+---+---+---+---+
                         +---> |'k'|'l'|'z'|'x'|'c'| 0 |
                               +---+---+---+---+---+---+

您无法从 a 本身知道它指向 3 个对象中的第一个;您无法从每个 a[i] 本身知道它指向一系列 char 对象。该信息必须单独跟踪。在 a 的情况下,我们有一个单独的变量 num_elements,它跟踪 a 中元素的数量。在每个 a[i] 的情况下,我们有字符串终止符来告诉我们每个字符串有多长。