目录


前言

在C语言基础阶段,我们学习过指针相关的一些基础内容,比如说:

1.指针是一个变量,用来存放地址,地址是唯一标识一块内存空间
2.指针的大小是固定的4 / 8个字节(32位平台 / 64位平台)
3.指针是由类型,指针的类型决定了指针的 + -整数的步长,指针解引用操作时候的权限
4.指针的运算

本篇文章及后面的几篇文章将会更加详细的去介绍和学习指针的进阶部分。(指针的内容在数据结构中会经常用到,所以一定要好好学习,打好基础~)

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_数组指针

接下来,我们继续探讨指针的高级使用


1、字符指针

在指针的类型中我们知道有一种指针类型为字符指针 char*
一般使用方式:

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针数组_02

还有使用方式如下:

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针数组_03

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针_04

注意观察区别:%C 与 %S :

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针_05

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_数组指针_06


这种方式是将字符串的首地址放到指针中,通过指针可以找到该字符串(千万不要理解成将字符串放到指针里面去,这是不可能的)。(类似与数组名就是首元素地址,但是跟数组还是有所区别的,这个字符串是一个常量字符串,无法被改变,如下图:)

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针数组_07

常量字符串不能改变


如果说我们想修改这个字符串,需要将其放入数组中,然后再去修改:

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针_08

扩展:在C语言中,内存可以被划分为栈区、堆区、静态区、常量区。

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针_09

栈区:局部变量,函数形参,函数调用
堆区:动态内存如malloc等申请使用
静态区:全局变量,static修饰的局部变量
常量区:常量字符串
常量区中的内容在整个程序的执行期间是不允许被修改的,且同一份常量字符串只会创建一份,不会重复创建存储。


看一面试题,输出什么?

#include 
int main()
{
char str1[] = "hello bit."; 
char str2[] = "hello bit."; 
char *str3 = "hello bit.";
char *str4 = "hello bit.";

if(str1 ==str2)
printf("str1 and str2 are same\n"); 
else
printf("str1 and str2 are not same\n");


if(str3 ==str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");


return 0;
}

结果展示:

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针_10

const修饰常量


分析:

创建数组需要开辟空间,数组arr1和arr2在内存空间所在位置是不同的,所以arr1 != arr2;

char* p1 = “abcdef”; char* p2 = “abcdef”; "abcdef"是常量字符串,不能被修改,在内存空间所占位置固定,char * p1 = “abcdef”; 是将该常量字符串的首地址放到字符指针p1中,char* p2 = “abcdef”;
是将该常量字符串的首地址放到字符指针p2中。

也就是说p1和p2存放都是常量字符串"abcdef"的首地址,所以p1 ==p2。(注意:同样的常量字符串只会存一份,不会同时存两份,所以不会开辟不同的空间来存储。

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_传参_11

**总结: **

这里arr1和arr2指向的是一个同一个常量字符串。
C /C++会把常量字符串存储到单独的一个内存区域当几个指针指向同一个字符串的时候,他们实际会指向同一块内存但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块

所以arr1和arr2不同,p1和p2相同。


2、指针数组

通过前面的学习,我们可以知道形如int arr1[5] = {0};的是整形数组,数组存放的是整形,形如char arr2[10] = {0};的是字符数组,数组存放的是字符。

同理,指针数组应该是数组,数组存放的是指针

    //指针数组 - 数组 - 存放指针的数组
    
    int* arr[4];//存放 整形指针的数组 - 指针数组
    char* ch[5];//存放 字符指针的数组 - 指针数组

指针数组的简单使用

看以下代码,猜猜结果是什么?

//指针数组的简单使用
int main()
{
    int a = 10;
    int b = 20;
    int c = 30;
    int d = 40;
    int* arr[4] = {&a, &b, &c, &d};
    int i = 0;
    for (i = 0; i < 4; i++)
    {
        printf( "%d ", *(arr[i]) );
    }
    return 0;
}

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_指针_12


我们知道数组名可以代表首元素的地址,请看下面这段代码:

#include
int main()
{
    int arr1[] = { 12345 }; //arr1--int*
    int arr2[] = { 23456 }; //arr2--int*
    int arr3[] = { 34567 }; //arr3--int*
    int* parr[] = { arr1,arr2,arr3 }; //存入每个数组首元素数组
    //通过arr数组打印arr1,arr2,arr3三个数组中的元素
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        int j = 0;
        for (j = 0; j < 5; j++)
        {
            printf("%d ", *( (parr[i] + j) );
        }
        printf("\n");
        
    }

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_数组指针_13


上面举例都是用整型指针数组,接下来我们来看一个字符指针数组的例子:

#include
int main()
{
    char* p1 = "student_zhang";
    char* p2 = "guofucheng";
    char* p3 = "liudehua";
    char* ch[3] = { p1,p2,p3 };
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        printf("%s\n", ch[i]);
    }
    return 0;
}

【C语言进阶】——指针(一)  (字符指针,数组指针,指针数组)   !!_字符指针_14


这里我们再复习一下,下面指针数组是什么意思 ?

int* arr1[10];  //整型指针的数组
char* ch[5];    //字符指针的数组
char* arr2[4];  // 一级字符指针的数组
char** arr3[5]; //二级字符指针的数组