返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言小知识之为什么要使用指针详析
  • 811
分享到

C语言小知识之为什么要使用指针详析

2024-04-02 19:04:59 811人浏览 薄情痞子
摘要

刚开始学习C语言的时候,感觉最难理解的就是指针,什么指针变量,变量指针,指向指针的变量,指向变量的指针?一堆概念,搞得人云里雾里的,今天不讨论这些概念的问题,从最底层来分析C语言中为

刚开始学习C语言的时候,感觉最难理解的就是指针,什么指针变量,变量指针,指向指针的变量,指向变量的指针?一堆概念,搞得人云里雾里的,今天不讨论这些概念的问题,从最底层来分析C语言中为什么要使用指针,指针存在的意义又是什么呢?

首先从一个简单的例子来看,写一段代码来交换x、y的值。


void main( void )
{
    u8 x = 10, y = 20;
    u8 temp;

    __asm( "sim" );                             //禁止中断
    SysClkInit();
    delay_init( 16 );
    LED_GPio_Init();
    Uart1_IO_Init();
    Uart1_Init( 9600 );
    ADC_GPIO_Init();
    __asm( "rim" );                             //开启中断
    while( 1 )
    {
        LED = ~LED;

        printf( "x = %d,y = %d\r\n", x, y );

        temp = x;
        x = y;
        y = temp;

        printf( "---> x = %d,y = %d \r\n\r\n\r\n", x, y );

        delay_ms( 200 );
    }
}

在STM8单片机中,交换x、y的值,并将值打印出来,打印结果如下:

image.png

通过第三个变量temp很轻松的就将x、y的值交换了。

但是为了程序的美观性,不想再主程序中写这么多的代码,于是决定用一个函数在外部来实现这个功能。


void swap( u8 x, u8 y )
{
    u8 temp;
    temp = x;
    x = y;
    y = temp;
}

void main( void )
{
    u8 x = 10, y = 20;
    __asm( "sim" );                             //禁止中断
    SysClkInit();
    delay_init( 16 );
    LED_GPIO_Init();
    Uart1_IO_Init();
    Uart1_Init( 9600 );
    ADC_GPIO_Init();
    __asm( "rim" );                             //开启中断
    while( 1 )
    {
        LED = ~LED;

        printf( "x = %d,y = %d\r\n", x, y );
        sawp( x, y );
        printf( "---> x = %d,y = %d \r\n\r\n\r\n", x, y );

        delay_ms( 200 );
    }
}

在主函数外面定义一个函数,专门用来交换x,y的值。程序运行结果如下:

image.png

此时发现x和y的值并没有交换,这是怎么回事?那么在交换函数内部,也将x和y的值打印出来。修改代码如下:


void swap( u8 x, u8 y )
{
    u8 temp;
    
    printf( "in: x = %d,y = %d\r\n", x, y );
    temp = x;
    x = y;
    y = temp;
    
    printf( "in: ---> x = %d,y = %d \r\n\r\n\r\n", x, y );
}

打印结果如下:

image.png

可以看到在交换函数内部,x和y的值已经交换了,但是在函数外部,x和y的值并没有交换。这是为什么呢?单步调试直接观察x和y在单片机内部分存储情况。

image.png

进入主程序之后,首先观察主函数内的x和y在内存中的存储情况,x值为10,也就是16进制的0x0A,在内存中0x000009的位置存储,y的值为20,也就是16进制的0x14,在内存中0x00000B,位置存储。

接下里进入到swap函数中。为了方便观察,将swap函数内部的x和y替换成了m和n。

image.png

可以看出在进入子函数之后,m和n的地址和值,都和main函数中的x和y一样。接下来交换m和n的值。

image.png

交换完成后发现,内存中0x000009位置的值和0x00000B位置的值亚发生了交换。然后退出子函数,返回到main函数中。

image.png

这时候奇怪的事情发生了,刚才内存中交换的值又变回来了?这是为什么呢?在这里就不得不说在C语言中关于局部变量的问题,局部变量在C语言中是没有固定的存储位置的,它是由系统的堆栈统一来管理的,当进入函数内部时,系统就会给这些局部变量临时分配一个存储空间存储它的值,当程序要离开函数时,系统就会将局部变量的值保存在堆栈中,然后变量的存储位置就被释放了。当程序进入另一个函数中时,又会给这个函数内部局部变量分配空间,这时候可能就会出现两个函数中的局部变量都使用了同一个内存空间。此时这个内存空间的值改变后,并不影响上一个函数中局部变量的值,因为上一个函数中的局部变量值此时在堆栈中存放。当程序要离开当前的这个函数时,又会将当前的局部变量值保存在堆栈中。回到上一个函数后,又将堆栈中存储的值恢复给变量,此时变量的地址又是临时申请的,可能此刻申请的地址值还是和上一次一样。但是并不代表这个地址就永远属于这个局部变量。

这个就很类似于超市中的储物柜,你要进去超市买东西,先将东西存到一个柜子中,买完东西后,又将东西存储物柜取了出来。然后隔了几个小时,又要去这个超市买东西,又需要将东西存起来,但是此时存储的柜子编号还是上上一次存储时一样。但是这并不能代表这个柜子的编号就是专属于你的了。它只是储物柜临时分配给你的空间,当你取出东西后这个空间就会被系统收回,如果你下一次还需要用,系统又会自动给你分配,但是这两次分配的刚好是一个编号而已。

那么要如何解决这种变量交换的问题呢?有两种方法,第一种就是直接将要交换的这个两个变量定义为全局变量,让它在程序运行的过程中独占一个地址空间,这样就不会有其他变量来使用这个位置了。但是这样的话就会比较浪费内存空间,只使用了一次,但是却要永久的占用。第二种方法就是直接使用指针。

下面将代码改成使用指针的方式。


void swap( u8 *m, u8 *n )
{
    u8 temp;   
    temp = *m;
    *m = *n;
    *n = temp;    
}
void main( void )
{
    u8 x = 10, y = 20;
    __asm( "sim" );                             //禁止中断
    SysClkInit();
    delay_init( 16 );
    LED_GPIO_Init();
    Uart1_IO_Init();
    Uart1_Init( 9600 );
    ADC_GPIO_Init();
    __asm( "rim" );                             //开启中断
    while( 1 )
    {
        LED = ~LED;

        printf( "x = %d,y = %d\r\n", x, y );
        sawp( &x, &y );
        printf( "---> x = %d,y = %d \r\n\r\n\r\n", x, y );

        delay_ms( 200 );
    }
}

在向swap函数传递参数的时候需要使用&符号。打印输出结果

image.png

此时x和y的值已经成功交换了。现在也将子函数内部的交换情况打印一下。


void swap( u8 *m, u8 *n )
{
    u8 temp;
    
    printf( "in: m = %d,n = %d\r\n", m, n );
    temp = *m;
    *m = *n;
    *n = temp;
    
    printf( "in: ---> m = %d,n = %d \r\n\r\n\r\n", m, n );
}

image.png

从输出的结果来看,怎么m和n的值一个时1021,一个时1020.这个值是什么呢?直接单步调试看。

image.png

此时main函数中x的地址变成了0x0003FD,y的地址变成了0x0003FC.接着进入子函数。

image.png

这时可以看出m的值为0x03FD,n的值为0x03FC.*m的值为0x0A也是就10,*0x14也就是20.
接下来开始交换值。

image.png

可以看出m和n的值没变,但是m和n的值交换了。接下来回到主函数中。

image.png

此时主函数中x和y的值也交换了。

那刚才串口打印出来的1021和1020是什么呢?1021的十六进制是0x03FD,1020的十六进制是0x03FC.也就是说刚才打印的m的值和x的地址一样,n的值和y的地址一样。

那为什么m和n会变成x和y地址,*m 和 *n又会变成 x 和 y 的值。这里就要说指针的本质了。在存储器内部,它是不认识什么变量和指针的,对于存储空间来说,它只有地址和值。也就是说在什么地址处,存储什么值。对于普通的变量来说,变量的名称就会被编译器编译成地址,也就是说x和y就是它自己地址的别名。x和y的值就是地址中对应的值。

当操作普通变量x和y的时候,系统默认操作的就是它的值。而指针刚好和它相反,指针默认是把地址作为它的值,当操作指针的时候,默认操作的就是地址。为了将普通变量和指针进行区分,那么如果要使用指针的时候,就需要给它贴一个标签,告诉系统,我这个是特殊变量,它是直接操作地址的,不是操作值的。

所以在定义指针的时候给变量前面加一个*号,就表示告诉系统,我这个是特殊的。比如定义了一个int *m。就表示告诉系统,当我默认操作m的时候,你就给我它的地址,而不要给我它的值。当需要取值的时候就需要添加上标签 *m,告诉系统我现在要取的值,不是地址,这是特殊情况,不要把默认的地址给我。

当要将普通变量传递给指针时,因为直接操作变量默认就是普通变量的值,而指针存贮的是地址,所以当普通变量和指针传递数据的时候,也要给普通变量添加一个标签 & ,这个符号就告诉系统,我现在不要默认的值,我要的是特殊情况的地址。

所以将x和y传递给指针的时候,前面要加&符号。

swap( &x, &y );对应的就是 swap( u8 *m, u8 *n );

刚才上面不是说了吗,指针默认的是地址,加上*号就是值了。那么这样直接传递过去不就是相当于 *m = &x 了吗?

由于这个子函数是定义和传值在一起操作了,省略了一步,标准操作应该是。

int *m;

m=&x;

先定义一个指针,然后将普通变量的特殊情况,也就是取普通变量的地址,传递给指针的默认情况。这样m的默认情况下就代表的值x的地址,而x的值就是*m。

如果定义变量和给变量赋值在一条语句时,上面的代码就可以简写为

int *m = &x;

所以上面的函数 swap( &x, &y ); 给指针传递值的时候,指针的定义和赋值是在一条语句完成的, swap( u8 *m, u8 *n ); 这是一种常用的简写形式。

在swap函数内部操作 *m 也就相当于直接操作的是x,操作 *n 就是直接操作的y,所以交换 *m 和 *n的值,就相当于交换x和y的值。

在没有使用指针时通过子函数交换,此时传递的是变量的值,相当于把变量的值拷贝了一份,给了子程序。

而有了指针之后,相当于将变量的地址直接给了子函数。相当于给变量x和y又起了一个别名。操作别名的时候,也就相当于直接操作的是x。

由此可见,指针只是为了方便编写程序而设置的一种给变量起别名的方法,也就是相当于给自己柜子配了了一把钥匙。只要别人有这个钥匙,也就可以打开你的柜子。所以指针在使用的时候会有危险性。

如果系统中有关键数据,那么如果这个数据用指针传递给了外部函数,那么当外部函数修改数据的时候,系统就会存在风险。有可能外部函数修改了一个值,而这个值是非法的,自己的系统就奔溃了。所以在使用指针的时候一定要注意安全性问题。

通过上面的例子,相信对指针就有了更深层次的理解了。它是为了方便操作变量而设置的特殊情况,是被贴了标签的变量。至于什么指针变量,变量指针,那都是起的名字而已,搞不清楚这些概念也不用去纠结,只要在使用的时候,知道如何使用就行了。

总结

到此这篇关于C语言小知识之为什么要使用指针的文章就介绍到这了,更多相关C语言使用指针内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言小知识之为什么要使用指针详析

本文链接: https://lsjlt.com/news/154560.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C语言小知识之为什么要使用指针详析
    刚开始学习C语言的时候,感觉最难理解的就是指针,什么指针变量,变量指针,指向指针的变量,指向变量的指针?一堆概念,搞得人云里雾里的,今天不讨论这些概念的问题,从最底层来分析C语言中为...
    99+
    2024-04-02
  • C语言指针之必须要掌握的指针基础知识
    目录一、指针概述指针的创建指针的大小如何使用指针二级指针二、野指针形成野指针的原因如何规避野指针三、指针的基本运算指针± 整数指针-指针四、指针和数组五、指针数组总结一、指针概述 指...
    99+
    2024-04-02
  • C语言学习之指针知识总结
    目录一、地址二、指针与指针变量三、指针的作用四、初学指针时常见的错误五、通过调用函数修改主调函数中的值六、指针与一维数组七、使用函数操作一维数组八、指针变量所占字节数九、静态数组的缺...
    99+
    2024-04-02
  • C语言基础知识点指针的使用
    目录一、指针的作用二、地址与指针三、指针变量四、数组与指针五、指针自加自减运算六、指向指针的指针七、指针变量作为函数形参八、函数指针九、函数指针数组十、指针的应用场景一、指针的作用 ...
    99+
    2024-04-02
  • C语言学习之指针的使用详解
    目录一、指针概念1.指针变量2.指针类型3.二级指针二、野指针1.野指针成因2.规避野指针三、指针运算1.指针±整数2.指针-指针3.指针关系运算四、指针数组1.指针和...
    99+
    2022-11-13
    C语言指针使用 C语言指针
  • 详解为什么指针被誉为C语言灵魂
    目录一、内存本质1.1、内存编址1.2、内存地址空间1.3、变量的本质二、指针是什么东西?2.1、变量放在哪?2.2、指针本质2.3、解引用2.4、活学活用2.5、看个小问题三、 结...
    99+
    2024-04-02
  • C语言浅析指针的使用
    目录指针等价形式转换函数指针主函数指针 指针是一个变量 (1) 作用:只能存储地址的值 (2) 大小:32位操作系统中占4字节;64位操作系统中占8字节 (3) 取地址:& ...
    99+
    2024-04-02
  • C语言指针使用实例分析
    今天小编给大家分享一下C语言指针使用实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。何为指针指针这玩意说白了,就是用来...
    99+
    2023-07-02
  • C语言为什么没有引用只有指针
    本篇内容主要讲解“C语言为什么没有引用只有指针”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言为什么没有引用只有指针”吧!什么是引用呢说白了引用&就是给已经存在的某个变量新建了一个名...
    99+
    2023-06-16
  • C语言中指针有什么用
    这篇文章主要介绍C语言中指针有什么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!(壹)  敢问指针为何物 1.1  指针的概念在计算机科学中,指针(Pointer)是编程语言中的一个对...
    99+
    2023-06-29
  • c语言指针有什么作用
    C语言指针是一种特殊的变量类型,用于存储内存地址。它们的作用包括:1. 动态内存分配:指针可以用于动态地分配内存,以便在程序运行时创...
    99+
    2023-09-14
    c语言
  • c语言指针的使用方法是什么
    在C语言中,指针是一个特殊的变量,它存储了一个内存地址的值。指针的主要作用是对内存中的数据进行直接操作,而不需要进行数据的拷贝。指针...
    99+
    2024-03-01
    c语言
  • C语言中指针有什么作用
    这篇“C语言中指针有什么作用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言中指针有什么作用”文章吧。一、内存本质编程的...
    99+
    2023-06-08
  • c语言指针的作用是什么
    C语言中的指针是一种特殊的数据类型,它用于存储变量的内存地址。指针的作用主要有以下几个方面:1. 内存管理:通过指针,可以动态地分配...
    99+
    2023-08-18
    c语言
  • C语言详解函数与指针的使用
    目录一、函数类型二、函数指针三、回调函数四、小结一、函数类型 C 语言中的函数有自己特定的类型 函数的类型由返回值,参数类型和参数个数共同决定,如 int add(int i, in...
    99+
    2024-04-02
  • C语言超详细讲解指针的使用
    目录指针概述自身类型指向类型代码例子数值型指针字符型指针单字符字符数组字符串型指针字符数组总结指针概述 C语言中指针也可以认为是一种类型,不同于数值型和字符型的类型。推演过去指针变量...
    99+
    2024-04-02
  • C语言中的指针怎么使用
    这篇文章主要介绍“C语言中的指针怎么使用”,在日常操作中,相信很多人在C语言中的指针怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言中的指针怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-17
  • c语言数组指针怎么使用
    在C语言中,数组和指针是密切相关的。数组名本身就是指向数组第一个元素的指针。因此,可以使用指针来操作数组。下面是一些常见的数组指针用...
    99+
    2023-10-18
    c语言
  • C语言中怎么使用指针函数和函数指针
    本篇内容介绍了“C语言中怎么使用指针函数和函数指针”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、指针函数当一个函数声明其返回值为一个指针...
    99+
    2023-06-16
  • C语言void指针的用法是什么
    C语言中的void指针是一种特殊的指针类型,可以用来表示任意类型的指针。具体来说,void指针可以指向任何数据类型的内存地址,但它本...
    99+
    2023-09-15
    C语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作