【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

这篇具有很好参考价值的文章主要介绍了【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

接着上次的函数的基本知识,今天我们来讲一讲🔍指针

目录

一、指针的概念

二、指针变量

三、野指针

四、字符指针

五、指针与数组

六、指针数组

七、数组指针

 八、指针与函数

总结


一、指针的概念

1.1、变量和地址

所谓指针,也就是内存的地址;所谓指针变量,也就是保存了内存地址的变量。

总结:指针就是变量,用指针存放地址(口语中说的指针通常指的是指针变量) 

1.2、指针变量和指针的类型

指针变量就是一个变量,它存储的内容是一个指针。在我们定义一个变量的时候,要确定它的类型。在定义指针变量时也是一样的,必须确定指针类型。int 变量的指针需要用 int 类型的指针存储,float 变量的指针需要用 float 类型的指针存储。

 指针类型决定了:指针解引用的权限有多大与指针走一步走多大字节(步长)

整型指针+1跳过一个整型。字符指针+1跳过一个字符

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....


二、指针变量

2.1、指针变量的定义及使用

(1)指针变量的定义

指针变量的定义形式如:数据类型 *指针名;例如:

int* x;//整型指针变量
float* f;//浮点型指针变量
char* ch;//字符型指针变量

指针的变量名分别是:x;f和ch。而int*;float*与char*分别是他们中存储的数据的类型。 

(2)指针变量的使用

取地址运算符&:单目运算符&是用来取操作对象的地址。例:&i 为取变量 i 的地址。对于常量表达式、寄存器变量不能取地址(因为它们存储在存储器中,没有地址)。
指针运算符*(解引用运算符 ):与&为逆运算,作用是通过操作对象的地址,获取存储的内容。例:x = &i,x 为 i 的地址,*x 则为通过 i 的地址,获取 i 的内容。

//声明了一个普通变量 a
int a;
//声明一个指针变量,指向变量 a 的地址
int *pa;
//通过取地址符&,获取 a 的地址,赋值给指针变量
pa = &a;
//通过间接寻址符,获取指针指向的内容
printf("%d", *pa);

2.2、指针运算

(1)指针与整数的加减运算

指针变量的自增自减运算。指针加 1 或减 1 运算,表示指针向前或向后移动一个单元(不同类型的指针,单元长度不同)。

(2)指针减指针

前提是两个指针指向同一个空间。

指针减指针得到两个指针间的元素个数

例: Arr[9]指向9与10中间部分(下标)

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....


三、野指针

3.1概念:

野指针就是指针指向的为止是不可知的(随机的,不正确的,没有明确限制的

3.2野指针的成因

(1)指针未初始化

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

(2)指针越界

如图:在第十次 访问时,可以进入到循环,相当于从第10个点向后访问4个字节,之后的字节不属于原数组,则越界了,则称为野指针。(只有在超出范围后,在会发生崩溃)

//越界访问
*int arr[10] ={ 0 };
int* p = arr;
int i=0;
for (i=0; i <= 10; i++)//共执行了11次,而arr数组总共只有10个元素
{
    *p = i;
    p++;
}

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

(3)指针指向的空间释放

int* test()//局部变量
{
    int a = 10;
    return &a;
}
int main()
{
    int *p=test();//返回值是a的地址,而局部变量在引用之后就会销毁。
    *p = 20;
    return 0;
}

3.3如何规避野指针

1.指针初始化 

2.小心指针越界。

3.指针指向空间释放即置NULL

4.指针使用之前检查有效性。


四、字符指针

4.1字符指针类型
在指针的类型中我们知道有一种指针类型为字符指针 char* ;
一般使用:
int main()
{
    const char* pstr = "hello ";//这里是把一个字符串放到pstr指针变量里了吗?
    printf("%s\n", pstr);
    return 0; }
本质是把字符串 hello首字符的地址放到了pstr中。

4.2例题

int main()
{
   char str1[] = "hello bit.";
   char str2[] = "hello bit.";
   const char *str3 = "hello bit.";
   const 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语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

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

 


五、指针与数组

之前我们可以通过下标访问数组元素,学习了指针之后,我们可以通过指针访问数组的元素。在数组中,数组名即为该数组的首地址,结合上面指针和整数的加减,我们就可以实现指针访问数组元素。

5.1、指针与二维数组

(1)二维数组的地址

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *p=a[0];//此处的p内存放的数组a第一行的地址。

5.2、多级指针

(1)多级指针(指向指针的指针)

指针变量作为一个变量也有自己的存储地址,而指向指针变量的存储地址就被称为指针的指针,即二级指针。依次叠加,就形成了多级指针。

指针变量也是一种变量,也会占用存储空间,也可以使用 &获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号 *。p1 是一级指针,指向普通类型的数据,定义时有一个 *;p2 是二级指针,指向一级指针 p1,定义时有两个*。例:假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....


六、指针数组

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

1.parr的第一个数组里放arr1的首元素地址

2.parr每个元素的类型是int*

3.该数组里每个元素都是指针,所以它是一个指针数组

4.Parr[i][j],也可以写成parr[i]+j,

5.相当于地址+j为向后挨个元素指向


七、数组指针

7.1、数组指针的定义

如以下语句:

int (*p)[10];
//解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。
//所以p是一个指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

 7.2、&数组名与数组名

让我们看一段代码

#include <stdio.h>
int main()
{
 int arr[10] = { 0 };
 printf("arr = %p\n", arr);
 printf("&arr= %p\n", &arr);
 printf("arr+1 = %p\n", arr+1);
 printf("&arr+1= %p\n", &arr+1);
 return 0; 
}

 运行结果如下

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。

实际上: &arr 表示的是数组的地址,而不是数组首元素的地址。(细细体会一下)

本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型。

数组的地址+1,跳过整个数组的大小。

 7.3、数组指针的使用

#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)//形参用数组来接受
{
    int i = 0;
    for(i=0; i<row; i++)
   {
        for(j=0; j<col; j++)
       {
            printf("%d ", arr[i][j]);
       }}}
void print_arr2(int (*arr)[5], int row, int col)//形参用数组指针来接受  
 {
    int i = 0;
    for(i=0; i<row; i++)
   {
        for(j=0; j<col; j++)
       {printf("%d ", arr[i][j]);}
        printf("\n");}}
int main()
{
   int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
   print_arr1(arr, 3, 5);
    //数组名arr,表示首元素的地址
    //但是二维数组的首元素是二维数组的第一行
    //所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址
    //可以数组指针来接收
    print_arr2(arr, 3, 5);
    return 0; }

 八、指针与函数

8.1、函数指针的定义  

returnType (*pointerName)(param list);
其中,returnType 为函数返回值类型,pointerNmae 为指针名称,param list 为函数参数列表。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。
注意( )的优先级高于*,第一个括号不能省略,如果写作returnType *pointerName(param list);就成了函数原型,它表明函数的返回值类型为returnType *。

8.2、指向函数的指针int (*pf[4])(int,int)={Add,Sub,Mul,Div};

函数指针数组,在函数指针的基础上,将指针变为指针数组

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....


总结

以上就是初阶指针的基本内容了!!!!非常感谢你能看到这里!

如果你觉得你有些想法和我一样,想和我一起提升自己可以关注私信我,与我一起进步,一起共同努力!!!!!文章来源地址https://www.toymoban.com/news/detail-402522.html

到了这里,关于【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【C语言初阶】带你轻松掌握指针基础知识完结篇——野指针,指针运算,指针和数组,二级指针

    【C语言初阶】带你轻松掌握指针基础知识完结篇——野指针,指针运算,指针和数组,二级指针

    君兮_的个人主页 勤时当勉励 岁月不待人 C/C++ 游戏开发 Hello,这里是君兮_,今天继续给大家更新0基础入门C语言的内容,我们这次主要更新的依然是初阶指针的基础知识 废话不多说咱们直接开始吧!! 概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有

    2024年02月16日
    浏览(13)
  • C语言之指针篇【超详细讲解,带你层层深入理解指针】

    C语言之指针篇【超详细讲解,带你层层深入理解指针】

    目录 一、关于指针 二、指针类型 1、整型指针的访问权限说明: 2、字符指针的访问权限说明: 3、指针的类型决定向前或向后一步走了多大距离 三、野指针相关知识 1、野指针的成因 ①指针未初始化 ②指针的越界访问 ③指针所指向的空间释放了 2、如何规避野指针 ①指针

    2024年02月02日
    浏览(22)
  • C语言/c++指针详细讲解【超详细】【由浅入深】

    C语言/c++指针详细讲解【超详细】【由浅入深】

    指针,是内存单元的编号。 内存条分好多好多小单元,一个小单元有 8 位,可以存放 8 个 0 或 1;也就是说,内存的编号不是以位算的,而是以字节算的,不是一个 0 或 1 是一个编号,而是 8 个 0 或 1 合在一起是一个编号。这个编号,就是地址。 内存条就分为好多小格子,一

    2024年01月21日
    浏览(11)
  • 初始C语言(7)——详细讲解有关初阶指针的内容

    初始C语言(7)——详细讲解有关初阶指针的内容

     第一章 “C“浒传——初识C语言(1)(更适合初学者体质哦!)  第二章 初始C语言(2)——详细认识分支语句和循环语句以及他们的易错点   第三章 初阶C语言(3)——特别详细地介绍函数   第四章 初始C语言(4)——详细地讲解数组的内容以及易错点   第五章

    2024年02月11日
    浏览(8)
  • 【运维知识大神篇】超详细的ELFK日志分析教程10(kafka集群原理+基本使用+zookeeper和kafka堆内存调优+kafka监控和压力测试+filebeat和logstash对接kafka)

    【运维知识大神篇】超详细的ELFK日志分析教程10(kafka集群原理+基本使用+zookeeper和kafka堆内存调优+kafka监控和压力测试+filebeat和logstash对接kafka)

    本篇文章继续给大家介绍ELFK日志分析,我们先前介绍了ELFK架构,zookeeper部署使用,kafka的部署,仅差kafka使用就将整个体系融汇贯通了。我们本篇文章将以kafka为核心,详细介绍kafka使用,最终将kafka融入ELFK架构中,大致内容见下面目录。 目录 kafka集群原理 一、专业术语 二、

    2024年02月04日
    浏览(9)
  • Web数据库基本知识,SQL基本语法

    当我们谈论整个技术栈时,实际上涉及了一系列步骤,而在Web开发中,这些步骤可以被具体化为以下几个阶段: DBMS-GUI-翻译器-查询语言 在web中具体如下: postgreSQL-Hasura-Apollo+ts-GraphQL 具体解释 DBMS(数据库管理系统): 作用: 数据库管理系统允许我们直接使用SQL语言来操作数

    2024年02月03日
    浏览(39)
  • python基本知识学习

    python基本知识学习

    在控制台输出Hello,World! 单行注释:以#开头 多行注释: 选中要注释的代码Ctrl+/ 三单引号 三双引号 第一个字符必须是字母表中字母或下划线 _ 。 标识符的其他的部分由字母、数字和下划线组成。 标识符对大小写敏感。 标识符也叫变量名,变量名就是一个变量的名字,例如

    2024年02月15日
    浏览(10)
  • Qt 基本知识

    QMainWindow:主窗口 菜单栏 工具栏 状态栏 QWidget:空白的窗口 所有界面组件的基类 QDialog:对话框类 new project Qt Widget Application qmake 后缀为 .pro 基类:QWidget Generate form 不要去掉 自动生成 ui 文件 Kit 一般使用第一个 widget.ui 界面加个 label 就行 可以在右下角进行调整 GUI 程序结构

    2024年02月22日
    浏览(12)
  • 图论的基本知识

    图论的基本知识

    1.数据结构 图论是数学的一个分支,研究图(Graph)的结构、性质以及它们之间的关系。图是由节点(或顶点)和边组成的一种数据结构,用于表示对象之间的关系。以下是一些图论的基本概念: 图(Graph): 图由节点(顶点)和连接节点的边组成。图可以分为有向图和无向

    2024年02月04日
    浏览(21)
  • 无人机基本知识

    无人机基本知识

    目录 前言 一、总体概况 二、机身 三、涵道 四、动力系统 1、 螺旋桨  2、电机 3、电调 4、电池 五、遥控器 六、自动驾驶仪(飞控) 1、组成 (1)传感器 (2)接口 2、飞控的连接 3、控制逻辑 4、作用 5、产品 七、地面站 八、数传 九、深度相机 总结 参考文献 四旋翼飞机

    2024年01月19日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包