让我们一起揭开指针的真面目

 文章目录


前言

走进指针的世界,我们先来了解一些指针的概念

1.内存会划分为一个个独立的内存单元

2.每个内存单元都有一个独立的编号 - 编号也成为地址

3.地址在C语言中被称为指针

4.指针(地址)需要储存起来 - 存储到变量中,这个变量就被称为指针变量

5.指针是由类型的,指针的类型决定了+-指针的步长(这一点特别重要哦,后面做很多面试题都会讲到)

6.指针的运算

7.int a = 10;   int *pa = &a;

8.指针(地址)的大小是固定的4/8个字节(32位平台。64位平台)


一、字符指针

#include <stdio.h>

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

    if (str1 == str2)//数组名是首元素的地址,str1和str2是指向不同地址的数组的首元素地址,所以str!=str2
        printf("str1 and str2 are same\n");
    else
        printf("str1 and str2 are not same\n");//not same

    if (str3 == str4)//str3 和 str4是两个常量字符串的名字,因为常量字符串是不可以被改变的,
                     //所以常量字符串只会在内存中存一个,不管名字怎么变,都会指向内存中仅有的一个字符串。
        printf("str3 and str4 are same\n");//same
    else
        printf("str3 and str4 are not same\n");

    return 0;
}

二、数组指针

数组指针到底使数组还是指针,答案是指针

类比:

整型指针 - 指向整型变量的指针,存放的是整形变量的地址的指针变量

字符指针 - 指向字符变量的指针,存放的是字符变量的地址的指针变量

数组指针 - 指向数组的指针,存放的是数组的地址的指针变量

下面来考考你,那个才是数组指针呢?

Int *p1 [10];   ->  [] 的结合率更高,p1[10] 就先形成了数组类,其次int * 指的是数组的元素类型位整型指针,即Int *p1 [10]是存放指针的数组

Int (*p2) [10];  ->  p2前面放了一颗*,有小括号,则p2和*先结合,形成指针,int []使数组的类型,所以是指针数组。(p2是数组指针变量)

数组名的深入理解

1.数组名是数组首元素的地址

2.但有2个例外:

(1)sizeof(数组名),这里的数组名不是数组首元素的地址,数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小,单位是字节

(2)&数组名,这里的数组名表示整个数组, &数组名取出的是整个数组的地址

        除此之外,所有的地方的数组名都是数组首元素的地址

int main()

{
    int arr[10] = { 0 };
    //这里就是数组首元素的两种不同写法  arr <==> &arr[0]
    printf("%p\n", arr);
    printf("%p\n", &arr[0]);
    return 0;
}
int main()

{
    int arr[10] = { 0 };
    printf("%p\n", arr);
    printf("%d\n", sizeof(arr));//4 / 8
    return 0;
}
int main()

{

    int arr[10] = { 0 };

    printf("%p\n", arr);                        //int *
    printf("%p\n", arr+1);//arr是指的首元素,打印%p即打印首元素的地址,加一就相当于指针往后挪一位,加4个字节
    printf("%p\n", &arr[0]);                //int *
    printf("%p\n", &arr[0]+1);//跳过一个整型元素,即4个字节
    //   整个数组的地址打印出来也是首元素的地址,和&arr[0]一样
    printf("%p\n", &arr);                    //int(*) [10]
    //但是&arr地址加一是跳过整个数组,arr是10个整形元素,即40个字节
    printf("%p\n", &arr+1);
    return 0;
}

二维数组的的每一行都可以理解为二维数组的一个元素

每一行又是一个二维数组的一个元素

每一行又是一个一维数组

所以二维数组就是一维数组的数组

那么数组指针怎么使用呢?

1.错误用法

int main()

{

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

int(*p)[10] = &arr;//&arr,取出来的是整个数组的地址,用什么来储存呢?int(*p)[10],即指针数组来储存

//原来的指针   int * p = arr;可以用for循环直接来遍历数组,但是数组指针一来就是整个数组的地址

//int(*p)[10] = &arr; -> (*p) <=> (*&arr) <=> arr  * 和 &抵消了

int i = 0;

for (i = 0; i < 10; i++)

{

//printf("%d ",*( (*p) + i));//这样就可以遍历数组了

printf("%d ", (*p)[i]);//等价于上面一行代码语句

//但终归这样用很麻烦,那数组指针怎么用呢?  -> 用于二维数组

}

return 0;

}

2.正确用法(数组指针怎么用呢?  -> 用于二维数组)

//常规方法

void Print(int arr[3][5], int r, int c)

{

        int i = 0;

        for (i = 0; i < 3; i++)

        {

        int j = 0;

        for (j = 0; j < 5; j++)

        {

                printf("%d", arr[i][j]);

        }

        printf("\n");

}

}

int main()

{

        int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };

        Print(arr, 3, 5);

        return 0;

}

//使用数组指针

void Print(int (*p)[5], int r, int c)

{

int i = 0;

for (i = 0; i < r; i++) {

int j = 0;

for (j = 0; j < c; j++) {

printf("%d ", * (*(p + i) + j));

}

printf("\n");

}

}

int main()

{

int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };

Print(arr, 3, 5);

return 0;

}

三、 指针数组

我们还是先使用类比的方式来引入指针数组的概念

        整型数组 - 存放整形的数组

        字符数组 - 存放字符的数组

        指针数组 - 存放指针的数组

模拟实现二维数组

int main()

{

        int arr1[] = { 1,2,3,4,5 };

        int arr2[] = { 1,8,3,9,5 };

        int arr3[] = { 1,4,3,0,5 };

        int *arr[] = { arr1,arr2,arr3 };

        int i = 0;

        for (i = 0; i < 3; i++)

        {

                int j = 0;

               for (j = 0; j < 5; j++)

               {

                        printf("%d ", arr[i][j]);

               }

               printf("\n");

        }

}

数组指针,是指向数组的指针,是指针

指针数组,是存放指针的数组,是数组


总结

本片笔记就到这里啦,

指针数组和数组指针这俩概念再初学的是时候真的很容易弄混,要细心一点欧

如果有不懂的宝子们,欢迎在评论区留言,我看到了会一一解答。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值