🌀 字符/串指针

在指针当中的类型中我们知道有一种指针类型为字符串指针 char*;

可以通过两种方法来访问一个字符或者是字符串。

1、第一种就是使用字符数组来存放字符串或者字符来实现操作。

2、下面所介绍的就是使用字符指针指向一个字符串,此时可不能定义数组。

一般的使用方法如下 👇 

#include<stdio.h>
int main(void)
{
char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_指针数组

字符型指针方法如下 👇 

#include<stdio.h>
int main(void)
{
char *str = "hello C";
printf("%s\n", str);
return 0;
}

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_字符串_02

运行结果🖊

hello C

如上示例 👆

定义了字符型指针变量 str,用字符串常量"hello C"为其进行赋初值。

注意🔥:这里并不是把"hello C"中的所有字符存放在 str 当中,只是把该字符串中的第一个字符'h'赋值给指针变量 str,然后printf()再通过'h'找到下一个元素直到遇到'\0'则停止。

本质上是把"hello C"这个字符串的首地址存储在了 str 当中。

如下图所示 👇

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_字符串_03


💥 常量字符串 

常量字符串顾名思义:就是不能被改变的字符/串。

如下示例代码 👇

#include<stdio.h>
int main(void)
{
char *str = "hello C";
char arr[] = "hello C";
*str = 'w';
arr[0] = 'w';
printf("%s\n", str);
printf("%s\n", arr);
return 0;
}

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_数组_04

上述代码所示 👆  

这里的*str指针变量指向这个字符串,严格意义上来说是指向这个字符串的起始地址。

*str 是不能改变字符串当中的值的,最终程序会"挂掉"。

arr  数组是可以改变字符串当中的值。

用调试当中的监视可以证明上述例子!

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_字符串_05

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_指针数组_06


代码崩溃的原因是告诉我们,当我们程序在写入对应的内存空间的时候发生了访问冲突。上述图中的报错才是真正的报错因为它是由系统来约束你的。这个字符串常量才是真正意义上的不可被修改。

💥重点核心常量字符串是不能被改变的,在内存当中的地址也是一样不能被改变的。


 🌀 指针数组 

一个数组的元素值为指针则是指针数组,指针数组是一组有序的指针的集合。 指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。

那么指针数组是怎么样的呢如下代码所示 👇

int* arr[5];//是什么?

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_数组_07

arr 是一个数组,有个元素,每个元素是一个整形指针,是一个存放整形指针的数组。

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_指针数组_08

 💥注意:除了每个元素的不同,而指针数组和普通数组在其它方面其实都是一样的!

#include <stdio.h>
int main(void)
{
int a = 12, b = 17, c = 55;

int *arr[3] = { &a, &b, &c };

int **parr = arr;
printf("%d, %d, %d\n", *arr[0], *arr[1], *arr[2]);
printf("%d, %d, %d\n", **(parr), **(parr+1), **(parr + 2));

return 0;
}

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_指针数组_09

运行结果 👇

  • 12 17 55 
  • 12 17 55  

上述运行结果都是相同的。

上述代码解释 👆   

arr 是一个指针数组,它包含了 3 个元素,每个元素都是一个指针,在定义 arr 的同时,我们使用变量 a、b、c 的地址对它进行了初始化,这和普通数组是多么地类似。

parr 是指向数组 arr 的指针,确切地说是指向 arr0 个元素的指针(首元素的地址),它的定义形式应该理解为​int *(*parr)​​,括号中的​*​表示 parr 是一个指针,括号外面的​int *​表示 parr 指向的数据的类型。arr0 个元素的类型为 int *,所以在定义 parr 时要加两个 *。

第一个 printf() 语句中,arr[i] 表示获取第 i 个元素的值,该元素是一个指针,还需要在前面增加一个 *(解引用) 才能取得它指向的数据,也即 *arr[i] 的形式

第二个 printf() 语句中,parr+i 表示第 i 个元素的地址,*(parr+i) 表示获取第 i 个元素的值(该元素是一个指针),**(parr+i) 表示获取第 i 个元素指向的数据

指针还可以与字符串相互结合进行使用,如下代码所示 👇  

#include <stdio.h>
int main(void)
{
char *arr[3] = { "C", "CSDN", "Electricity" };
printf("%s <==> %s <==> %s\n", arr[0], arr[1], arr[2]);
return 0;
}

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_指针数组_10

需要注意的是,字符数组 str 中存放的是字符串的首地址,不是字符串本身,字符串本身位于其他的内存区域,和字符数组是分开的。

也只有当指针数组中每个元素的类型都是char *时,才能像上面那样给指针数组赋值,其他类型不行。

改成下面的形式,与上面的数组是等价的,如下代码所示 👇

#include <stdio.h>
int main(void)
{
char *str0 = "C";
char *str1 = "CSDN";
char *str2 = "Electricity";
char **str[3] = { str0, str1, str2 };
printf("%s <==> %s <==> %s", str[0], str[1], str[2]);

return 0;
}

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_指针数组_11

运行结果C <==> CSDN <==>  Electricity

🔥 指针数组使用场景 

接下来,演示下指针数组的应用场景,情况。

如下代码所示 👇

#include<stdio.h>
int main(void)
{
int a[5] = { 1, 2, 3, 4, 5 };
int b[5] = { 6, 7, 8, 9, 10 };
int c[5] = { 11, 12, 13, 14, 15 };
int *pa[3] = { a, b, c };
for (int i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%-2d ",pa[i][j]);
}
printf("\n");
}
return 0;
}

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_字符串_12

运行结果如下所示 👇 

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_字符串_13

【C语言】进阶指针Ⅰ 字符串指针、常量字符串、指针数组、指针数组使用常见。_数组_14

编辑

💥重点核心指针数组本质上其实是个数组,数组中存放的是指针(地址) 而已😅