欢迎光临
我们一直在努力

数组与字符串 | C指针基础(二)

数组、字符串和指针 | C指针基础(二)

  • 数组名 arr、&arr 与 &arr[0] 打印结果为何相同?
  • 字符串与指针
  • 利用指针读取数组

数组名 arr、&arr 与 &arr[0] 打印结果为何相同?

先运行下面这段程序:

#include <stdio.h>

int main() {
int arr[10] = {0};
printf("%d\\n", arr);
printf("%d\\n", &arr);
printf("%d\\n", &arr[0]);
return 0;
}

运行后你会发现,三个 printf 打印出来的结果完全相同,并且输出的都是地址。 这是因为:在表达式中,数组名 arr 会退化为指向首元素的指针,其值等于 &arr[0];而 &arr 取的是整个数组的地址,虽然类型不同,但地址数值也与首元素地址相同,因此三者打印结果一致。

也就是说:在C语言中,数组名本质上是一个指针,存储的是该数组第一个元素的内存地址。数组名的取地址和取第一个元素的地址是同一个操作。

字符串与指针

我们知道,在 C 语言中,字符串本质上也是一种字符数组,因此可以仿照上一节的方式运行下面的程序:

#include <stdio.h>

int main() {
char name[10];
char name1[10];
char name2[10];
scanf("%s", &name);
scanf("%s", name1);
scanf("%s", &name2[0]);
printf("%s\\n", &name);
printf("%s\\n", name1);
printf("%s\\n", &name2[0]);
return 0;
}

运行后你会发现,分别向 name、name1、name2 输入内容后,三个 printf 都能正确打印出最开始输入的字符串,而不是像上一节那样打印地址。

这是因为两次示例使用的格式占位符不同:数组示例中使用 %d,打印的是指针本身保存的地址数值;而字符串示例中使用 %s,printf 会沿着传入指针所指向的首字符开始,逐个读取并输出字符,直到遇到 \\0 结束符,因此最终打印出来的是完整的字符串内容。

对比示例:

// 数组示例:%d 输出地址
printf("%d\\n", arr); // 输出类似:一串地址数值

// 字符串示例:%s 输出字符串
printf("%s\\n", name); // 输出类似:hello(你输入的内容)

也就是说:在 C 语言中,字符串是字符数组,字符串名同样可以看作指向首字符的指针;&name、name、&name[0] 在数值上都等于字符串首字符的地址。

利用指针读取数组

前面已经知道,数组名在表达式中会退化为指向首元素的指针,因此除了用下标访问,还可以利用指针来读取数组元素。先看下面的程序:

#include <stdio.h>

int main() {
int arr[10] = {10001, 20003, 0};
printf("%d\\n", *arr); // 等价于 arr[0]
printf("%d\\n", *(arr + 1)); // 等价于 arr[1]
return 0;
}

运行后会输出:

10001
20003

根据上一篇笔记可知,* 是解引用运算符,用来取出指针所指向的内容;而数组名 arr 本身就表示首元素地址,所以 *arr 就是取出第一个元素,等价于 arr[0]。

同理,arr + 1 并不是把地址简单地加 1 个字节,而是按照指针指向的类型自动步进。因为 arr 是 int 类型数组,arr + 1 会指向下一个 int 元素,也就是 arr[1] 的地址;再对它解引用,就得到第二个元素的值。

下面两组写法完全等价:

printf("%d\\n", arr[0]); // 下标方式读取第一个元素
printf("%d\\n", *arr); // 指针方式读取第一个元素

printf("%d\\n", arr[1]); // 下标方式读取第二个元素
printf("%d\\n", *(arr + 1)); // 指针方式读取第二个元素

推广到一般情况,arr[i] 与 *(arr + i) 等价,这就是 C 语言中指针与数组之间的联通关系。

赞(0)
未经允许不得转载:171主机测评 » 数组与字符串 | C指针基础(二)
分享到: 更多 (0)

评论 抢沙发

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