假设我们有一个字符串数组,初始化如下:
char **a = malloc(3 * sizeof(char*)); //edited
a[0]="asd";
a[1]="fghj";
a[2]="klzxc";
我们如何打印这个2D阵列的第一个维度(3(?
我们如何打印这个2d数组的第一个维度(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] = %sn", 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]
的情况下,我们有一个字符串终止符来告诉我们每个字符串有多长
我们如何打印这个2D数组的第一个维度(3(
前面几点:
准确地说,char **a
不是一个2D数组,它是指向char
的指针。
使用这种内存分配的一种更安全的方法是使用取消围栏的指针而不是类型,这种方法有助于维护代码:
char **a = malloc(sizeof *a * 3);
另一件需要注意的事情是,分配给这些指针的字符串文字是只读的,不能更改。
回答您的问题:
要知道第一个维度,,即分配的指针数量,您需要记住它,可能会存储它,没有可移植的方法来检索事后分配的指针的数量。
然而,有一些不可移植的方法可以做到这一点:
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
当函数返回分配的字节数时,将其返回值除以指针的大小将检索实际的指针数。
如果您需要实际的可编辑字符数组:
如果你想拥有一个可以编辑和更改的字符数组,你还必须为这三个指针中的每一个分配内存。
例如
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]