当前位置: 首页 > article >正文

C语言基础——指针(4)

一.    字符指针变量
       字符指针变量的使用和整型指针变量的使用方法相似,以下是其基本使用方法的例子:
 358e20ab84944910a78a798187fa162d.png
(1)字符指针变量还有一种使用方法:
                   const char* p = "abcd"
需要注意的是,这里并不是把字符串abcd放到了指针变量p中,而是只将这个字符串中的第一个元素的地址赋给了p,我们可以用下面这个代码来理解:
                   char arr[] = "abcd";
                   char* ch = arr;
                   printf("%c", *ch);
ch这个指针变量实际存放的是数组中首元素a的地址。



(2)const char* p = "abcd";用%s打印这个字符串的时候,只需要提供首元素的地址即可。
 

92726715fd8049408fd62e5a82692315.png


(3)const char* p = "abcd"这是一个常量字符串,意味着里面的内容不能修改


(4)在c语言中,用相同的字符串去初始化不同的数组时,会开辟出不同的空间:但是,用不同的指针指向同一个字符串时,其实会指向同一块空间,我们用两个代码来验证:
 
 6c7c48010ec7446ba0e23e611cf6f7f8.png


316f4107dda94bef86b5aec62b2e1316.png



二.    数组指针变量
       整型指针变量时存放整型变量的地址,字符指针变量是存放字符变量的地址,那么同理,数组指针变量是存放数组的地址。
       在介绍数组指针前,我们需要区分一下数组指针和指针数组,在前面的学习中,我们已经了解了指针数组,它其实是存放指针的数组,而数组指针正好相反,它是存放数组地址的指针。在记忆上,可以着重记忆后面两个字,指针数组它的重点是数组,而数组指针它的重点是指针。


以下是数组指针变量写的方式:
                            int (*p)[5];
理解的时候,我们可以按照以下顺序来理解:
       *先和p结合,说明变量p是一个指针变量——变量p指向它后面的内容,在这里指向的是一个大小为5的数组——这个数组的类型为整型。
       我们知道,数组名就是数组首元素的地址,而&数组名,就是整个数组的地址了。在对数组指针变量初始化的时候,我们就可以用&数组名来操作:
                     int (*p)[5]=&arr;



为了更灵活的应用,我们将char * ch[5] 放入数组指针中去:
              char *(*pch)[5]=char * ch[5]
和上面的理解方式相同:*与pch结合,表示pch是一个指针变量,这个指针变量指向一个大小为5的数组,而这个数组的类型为char*。



下面,我们用数组指针变量的内容来打印一个数组:
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int (*p)[10] = &arr;
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", (*p)[i]);
    }
    return 0;
}
注意:*p将p这个指针变量解引用,代表的是数组arr,也就等价于arr[i];arr[i]又等价于          *(arr+i),这样更有助于我们理解二维数组传参。




三.    二维数组传参的深入理解
二维数组可以看作每个元素是一维数组的数组,二维数组的首元素就是第一行,是一个一维数组。所以,二维数组的数组名表示的就是第一行的地址,二维数组传参本质上就是传递了第一行的一维数组的地址,假设我们要打印一个二维数组,代码如下:
void print(int (*p)[5], int a, int b)
{
    for (int i = 0; i < a; i++)
    {
        for (int j = 0; j < b; 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;
}
 d59e05d18b0a4a7aae671ffe765cca1b.png



以下是对这段代码中重点内容的解释:
(1)由于二维数组传参传过去的是第一行的一维数组的地址,那么在接收参数时,就应该用数组指针变量的形式来写,也就是int(*p)[5]。
(2)*(*(p + i) + j)
我们从内向外依次来解释理解:

由于p存放的是一个一维数组的地址,那么p+i表示的就是每加i就跳过一个一维数组,用*(p+i)的方式来找这个二维数组中的每一个一维数组,*(p+i)可以看作一个一维数组arr1;*(*(p + i) + j)就可以看作 *(arr1+j),而这又等价于arr1[j],这样就可以理解二维数组的传参了。



 


http://www.kler.cn/a/449671.html

相关文章:

  • 链表的详解
  • 数据库操作【JDBC HIbernate Mybatis】
  • Debian 12 安装配置 fail2ban 保护 SSH 访问
  • 【C++语言】多态
  • 【视觉SLAM:八叉树地图(Octree Map)概述】
  • Cline 3.0发布:从AI编程助手到通用智能体平台的进化
  • WebRTC服务质量(09)- Pacer机制(01) 流程概述
  • Nautilus源码编译傻瓜式教程一
  • 20241230 基础数学-线性代数-(1)求解特征值(numpy, scipy)
  • 如何调大unity软件的字体
  • 大恒相机开发(3)—大恒相机工业检测的实际案例
  • css 裁剪 clip-path
  • STM32MP1linux根文件系统目录作用
  • 深入探索鸿蒙NEXT:设计原理、架构揭秘与ArkTS应用开发【书籍推荐】
  • 面试经典题目:LeetCode55_跳跃游戏
  • 基于Java+Swing+Mysql的超市客户关系管理系统
  • uniapp+vue开发app,蓝牙连接,蓝牙接收文件保存到手机特定文件夹,从手机特定目录(可自定义),读取文件内容,这篇首先说如何读取,手机目录如何寻找
  • Windows中Microsoft Edge兼容性问题|修复方案
  • Git的简介
  • .NET Core 项目配置到 Jenkins
  • dbcat mysql 慢日志监控利器
  • 潜在狄利克雷分配LDA 算法深度解析
  • Java面试要点94 - Java分布式锁的实现与应用
  • OSPF的基本配置
  • 从0-1逐步搭建一个前端脚手架工具并发布到npm
  • 基于python使用UDP协议对飞秋进行通讯—DDOS