欢迎光临
我们一直在努力

【C基础】C语言里 char ** 到底怎么理解?为什么字符串数组传参后会变成二级指针

我觉得目前大多数人对于指针的理解可能还是处于懵懵懂懂的状态,当然,我也不例外,今天在做项目的过程中,发现其实这个点还是有点不是很清楚,所以我索性写一篇关于这个指针的总结。

很多人在学 c 的过程中,看到指针会很懵,尤其是这种代码:

char *tokens[10];

传进函数后却写成:

int func(char **tokens)

明明数组里的每个元素已经是 char * 了,为什么函数参数还要再加一个 *?

这个问题其实不难,关键是要分清楚: “数组里的元素是什么” 和 “传给函数的是什么” 不是一回事。

一、先看 char * 和 char ** 分别表示什么

char *:表示“字符指针”,通常拿来表示一个字符串。

例如:

char *s = "hello";

这里 s 指向字符串 "hello",所以:

  • s 是一个指针

  • *s 是一个字符

也就是说:

char * -> 一个字符串

char **:表示“指向 char * 的指针”。

也就是说,它指向的不是字符,而是一个“字符串指针”。

char *s = "hello";
char **p = &s;

这里:

  • s 是 char *

  • p 是 char **

  • p 存的是 s 的地址

所以:

char ** -> 指向字符串指针

你也可以暂时把它通俗地理解成:“一组字符串的入口”

二、为什么 char *tokens[10] 传参后会变成 char **

先看定义:

char *tokens[10];

这表示:

  • tokens 是一个数组

  • 数组里每个元素的类型是 char *

也就是说:

tokens[0] // 类型是 char *
tokens[1] // 类型是 char *
tokens[2] // 类型是 char *

但是,当数组作为函数参数传递时,数组名会退化成指针。

比如:

void func(char **tokens)
{
printf("%s\\n", tokens[0]);
}

调用:

func(tokens);

这里传进去的不是整个完整数组实体,而是:数组第一个元素的地址(之所以这样设计,是因为数组元素在内存里是连续存放的,拿到第一个元素的地址后,就能顺着访问后面的元素。)

tokens == &tokens[0] // 在函数传参这种场景里理解成这样就行

而数组第一个元素的类型是什么?是:char *

那么“第一个元素的地址”类型自然就是:char **

所以函数参数写成:char **tokens

三、为什么“元素已经是 char *”了,还要再加一个 *

因为函数里接收的不是“元素本身”,而是“元素的地址”。

这是很多人最容易绕进去的地方。

看这两个东西:

1. 单个元素:tokens[0]

它的类型是:char *,因为它本身就是数组里的一个元素。

2. 整个数组名:tokens

它不是某个元素,而是数组的起始位置。 数组传参时,它会变成“指向第一个元素的指针”。

而第一个元素类型是 char *,所以:tokens   -> char **

所以不要把这两个混了:

  • tokens[0] 是 char *

  • tokens 传参后是 char **

四、结合代码看

例子 1:定义字符串数组

#include <stdio.h>

int main() {
char *tokens[3];

tokens[0] = "SET";
tokens[1] = "name";
tokens[2] = "alice";

printf("%s\\n", tokens[0]);
printf("%s\\n", tokens[1]);
printf("%s\\n", tokens[2]);

return 0;
}

这里:

  • tokens 是数组

  • tokens[0]、tokens[1]、tokens[2] 都是 char *

例子 2:把这个数组传给函数

#include <stdio.h>

void print_tokens(char **tokens) {
printf("%s\\n", tokens[0]);
printf("%s\\n", tokens[1]);
printf("%s\\n", tokens[2]);
}

int main() {
char *tokens[3];

tokens[0] = "SET";
tokens[1] = "name";
tokens[2] = "alice";

print_tokens(tokens);

return 0;
}

这里函数参数为什么是 char **tokens?

因为传进去的是数组名 tokens,数组名传参后退化成指针。 而数组元素类型是 char *,所以参数类型就是:char **

五、总结

char ** 并没有那么神秘。它本质上表示:指向 char * 的指针

如果你定义的是:char *tokens[10];

那么数组里的每个元素都是 char *。 而当这个数组传给函数时,传过去的是“第一个元素的地址”,也就是“指向 char * 的指针”,数组名退化成指向第一个元素的指针,所以传参时可以把它看成第一个元素的地址。所以函数参数要写成:char **tokens

你只要记住下面这两句话,基本就不会乱:

  • char *:一个字符串

  • char **:指向字符串指针,常用来接收字符串数组参数

0voice · GitHub

赞(0)
未经允许不得转载:171主机测评 » 【C基础】C语言里 char ** 到底怎么理解?为什么字符串数组传参后会变成二级指针
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址