我想结束与此混淆 char **
当一次创建一个字符数组(字符串)数组时,char **实际上如何实现这一目标?
我得到的char *是一个指向char *array[]char的指针,这是一个char指针数组,但究竟是做char **什么的,它是如何做到的?
此外,当我听到dereferences这个词时,它会让我认为指针被删除了指针取消引用究竟是什么意思?更改指针指向的值?
谢谢
Joh*_*ode 13
"解除引用"指针意味着访问指针指向的值.假设以下声明:
int a = 10;
int *p = &a;
Run Code Online (Sandbox Code Playgroud)
这是两个变量的假设记忆图:
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- a 0x80001000 0x00 0x00 0x00 0x0A p 0x80001004 0x80 0x00 0x10 0x00
a包含整数值10. p包含地址a(0x80001000).如果我们想访问athrough 的内容p,我们使用间接运算符取消引用 .因此,表达式等同于表达式.如果我们写的p**pa
*p = 16;
Run Code Online (Sandbox Code Playgroud)
这和写作一样
a = 16;
Run Code Online (Sandbox Code Playgroud)
这是一段简短的代码片段,展示了如何使用类型的对象char **来创建字符串数组:
#include <stdlib.h>
#define N 20 // For this example, we will allocate 20 strings
#define LENGTH 10 // of 10 characters each (not counting 0 terminator)
...
char **arr = malloc(sizeof *arr * N);
if (arr)
{
size_t i;
for (i = 0; i < N; i++)
{
arr[i] = malloc(sizeof *arr[i] * (LENGTH + 1));
strcpy(arr[i], " ");
}
}
Run Code Online (Sandbox Code Playgroud)
逐行完成,
char **arr = malloc(sizeof *arr * N);
Run Code Online (Sandbox Code Playgroud)
分配N个元素,每个大到足以存储一个字符指针(块sizeof *arr== sizeof (char *)因为类型*arr== char *),并分配所得到的指针值到arr.IOW,arr指向第一个指针char,因此指向类型char **.请注意,如果将声明和函数调用分开,它看起来就像
char **arr;
...
arr = malloc(sizeof *arr * N);
Run Code Online (Sandbox Code Playgroud)
我们要分配的结果malloc来arr,没有什么arr 指向.
if (arr)
Run Code Online (Sandbox Code Playgroud)
malloc失败是可能的,因此我们希望在使用之前检查结果.如果malloc失败,它将返回NULL指针值.
{
size_t i;
for (i = 0; i < N; i++)
{
arr[i] = malloc(sizeof *arr[i] * (LENGTH + 1));
Run Code Online (Sandbox Code Playgroud)
对于每个字符指针arr[i],我们为LENGTH + 1个元素分配一个足够大的内存块,每个元素足够大以容纳一个char值(sizeof *arr[i] == sizeof (char)因为类型为*arr[i] == char;注意sizeof (char)总是为1)并将结果赋值给arr[i].
由于我们使用单独的malloc调用分配每个字符串,因此它们在内存中不太可能是连续的.这是另一个显示上述代码可能结果的内存映射:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
arr 0x80001000 0xA0 0xCC 0x00 0x00
...
arr[0] 0xA0CC0000 0xA0 0xCC 0x20 0x00
arr[1] 0xA0CC0004 0xA0 0xCC 0x20 0x40
arr[2] 0xA0CC0008 0xA0 0xCC 0x21 0x28
...
arr[19] 0xA0CC0014 0xA0 0xCC 0x23 0x10
...
arr[0][0] 0xA0CC2000 ' ' ' ' ' ' ' '
arr[0][4] 0xA0CC2004 ' ' ' ' ' ' ' '
arr[0][8] 0xA0CC2008 ' ' ' ' 0x00 0x??
...
arr[1][0] 0xA0CC2040 ' ' ' ' ' ' ' '
arr[1][4] 0xA0CC2044 ' ' ' ' ' ' ' '
arr[1][8] 0xA0CC2048 ' ' ' ' 0x00 0x??
...
指针是一种将地址保存到值的类型,而不是保存实际值.
因此,在char*p的情况下,一旦分配,p将包含地址A.解除引用该指针意味着访问存储在地址A的值.您可以在char*中存储字符串的原因是因为分配的内存是连续的.因此,A是存储第一个字符的地址,A + 1是存储第二个字符的地址,依此类推.
在char**pp的情况下,它存储char*的地址.调用此地址B.因此,解除引用pp意味着访问地址B处的值,该值恰好是char*,恰好包含字符串.以同样的方式,B + 1(实际上是B + sizeof(char*))存储下一个值,这是另一个字符串.
取消引用pp两次(即**pp)意味着您首先访问地址B处的值,例如A,然后再次解除引用以获取地址A处的值,这是某个字符.