深入理解指针(2) ---学习笔记分享

目录:

(1)数组名的理解

(2)使用指针访问数组

(3)一维数组传参的本质

(4)冒泡排序

(5)二级指针

(6)指针数组

(7)指针数组模拟二维数组

1.数组名的理解

数组名是数组首元素的地址;

下面做一个小测试:

int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("&arr[0] = %p\n",&arr[0]);
printf("arr = %p\n",arr);

但是有两个例外

(1)sizeof(数组名) 这里的数组名表示整个数组,计算的是整个数组大小

(2)&数组名 这里的数组名也是整个数组,取出的是整个数组的地址:数组的地址+1 要跳过一个数组

其他的所有数组名都是数组首元素的地址

2 使用指针访问数组
int arr[10] = {0};
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
//使用下标的方式访问数组
for(i = 0;i < sz;i++)
{
    scanf("%d",&arr[i]);
}
for(i = 0;i < sz;i++)
{
    printf("%d\n",arr[i]);
}
 
//使用指针来访问数组
int arr[10] = {0};
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int* p = &arr[0];//也可以直接 = arr
​
for(i = 0;i < sz;i++)
{
    scanf("%d",p + i);//p+i是下表为i元素的地址//这里的p也可以直接携程arr
}
for(i = 0;i < sz;i++)
{
    printf("%d\n",*(p + i));//解引用下标为i的元素的地址  //*(arr + i)完全等价于arr[i]
}

注意:加法符合交换律 --->*(arr + i) 等价于 *(i + arr)

另外 arr[i] 也等价于 i[arr]; //[]只是一个操作符

1、数组就是数组,是一块连续的空间,是一个可以存放一个或者多个数组的

2、指针变量是一个变量,是可以存放地址的变量

数组和指针不是一回事,但是可以是一种指针来访问数组

为什么可以使用指针来访问数组呢?

(1)数组在内存中是连续存放的

(2)指针的运算可以很方便地遍历数组,取出数组内容

3.一维数组传参的本质
void test(int arr[10])//传来的是首元素的地址int* arr
         //所以写成arr[]也行
{
    int sz2 = sizeof(arr) / sizeof(arr[0]);
    printf("sz2 = %d\n",sz2);//打印sz2 = 1
}
int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int sz1 = sizeof(arr) / sizeof(arr[0]);
    printf("sz1 = %d\n",sz1);//sz1 = 10;
    test(arr);//arr是数组名,数组名表示数组首元素的地址,传过去的是首元素的地址
    //数组传参的本质:传递的是数组首元素的地址
    //所以形参即使写成数组的形式,本质上也是一个指针变量
    return 0;
}

数组传参的时候,形参可以写成数组,也可以写成指针

写成数组的形式,最简单,是为了方便理解,容易接受这种语法

但是即使写成数组的形式,本质上还是指针

void test(int* arr,int sz)//
{
    int i = 0;
    for(i = 0;i < sz;i++)
    {
        printf("%d ",arr[i]);
        //printf("%d ",*(arr + i));;两种写法均可以
    }
}
4.冒泡排序

先搞清楚冒泡排序是怎么样的:两两相邻的元素比较,不满足顺序就交换,满足顺序就找下一对

void input(int* arr,int sz)
{
    int i = 0;
    for(i = 0;i < sz;i++)
    {
        scanf("%d",arr+i);
    }
}
​
void bubble_sort(int* arr,int sz)
{
    int i = 0;
    for(j = 0;j < sz - 1 - i;j++)
    {
        if(arr[j] < arr[j+1])
        {
            flag = 0;
            //交换
           	int temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
    }
}
​
void print_arr(int* arr,int sz)
{
    int i = 0;
    for(i = 0;i < sz;i++)
    {
        printf("%d ",arr[i]);
    }
}
int main()
{
    int arr[10] = {0};
    //输入一些值
    int sz = sizeof(arr) / sizeof(arr[0]);
    input(arr,sz);
    //排升序(冒泡排序)
    bubble_sort(arr,sz);
    print_arr(arr,sz);
    return 0;
}

但是存在情况:10 9 7 8 6 5 4 3 2 1,这种情况用上面的代码处理起来就非常浪费时间;

于是我们可以对上述代码稍作修改:增加哨兵值

void bubble_sort(int* arr,int sz)
{
    int i = 0;
    for(i = 0;i < sz;i++)
    {
        int flag = 1;//哨兵值
        int j = 0;
        for(j = 0;j < sz - 1 - i;j++)
        {
            flag = 0;
            //交换
            int temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
        if(flag)
            break;
    }
}
5.二级指针

(前面讲的都是一级指针)

什么是二级指针?

int a = 10;
int* pa = &a;//pa是一级指针变量
int** ppa = &pa;//ppa就是二级指针变量

地址 指向的值 指向的变量

0x0012ff40 10 a (int)

0x003f4800 0x0012ff40 pa(int*)

0x004ff460 0x003f4800 ppa(int**)

二级指针变量是用来存放一级指针变量的地址

解引用:**ppa 就是a

*ppa 就是pa

注意:二级指针和二维数组没有对应关系

可以有多级指针,一般不会超过三级指针

6.指针数组

指针数组

到底是指针还是数组???

char arr[10];//字符数组——存放字符的数组

int arr[5];//整型数组——存放整型的数组

那么,指针数组——存放指针的数组,数组的每个元素都是指针类型

指针数组的每个元素都是地址(指针),又可以指向同一块区域

char* arr[5];//存放字符指针的数组

int* arr[6];//存放整型指针的数组

int main()
{
    int a = 10;
    int b = 20;
    int c = 30;
    int* arr[3] = {&a,&b,&c};
    int i = 0;
    for(i = 0;i > 3;i++)
    {
        printf("%d ",*(arr[i]));
    }
    return 0;
}
7.指针数组模拟二维数组
#include<stdio.h>
int main()
{
    int arr1[5] = {1,2,3,4,5};
    int arr2[5] = {2,3,4,5,6};
    int arr3[5] = {3,4,5,6,7};
    //数组名是数组首元素地址,类型是int*的,就可以存放在parr数组中
    int* parr[3] = {arr1,arr2,arr3};
    int i = 0;
    int j = 0;
    for(i = 0;i < 3;i++)
    {
        for(j = 0;j < 5;j++)
        {
            printf("%d ",parr[i][j]);//*(*(parr + i) + j)
        }
        printf("\n");
    }
    return 0;
}

运行结果如图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值