码迷,mamicode.com
首页 > 其他好文 > 详细

C之指针(二十四)

时间:2018-04-17 23:44:21      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:C语言   指针   

        在 C 语言中用的最多的就是指针了,指针同样也是 C 语言的精华所在了。我们今天就来看看指针到底是什么,它是如何使用的。

        我们先来回想下变量,在程序中的变量只是一段存储空间的别名,那么是不是必须要通过这个别名才能使用这段存储空间呢?答案肯定不是的,我们还可以通过指针来使用这段存储空间。在指针声明时,* 号表示所声明的变量为指针。在指针使用时,* 号表示取指针所指向的内存空间中的值。我们通过下面这幅图可以更加直观的看出他们的关系

技术分享图片

        通过这个图片我们是不是更加直观的看出它们的关系呢。上面即表示的是变量 p 保存着变量 i 的内存地址,即 p <--> &i;    *p <--> i

        下来我们通过示例代码进行分析说明,代码如下

#include <stdio.h>

int main()
{
    int i = 0;
    int* pI;
    char* pC;
    float* pF;
    
    pI = &i;
    
    *pI = 10;
    
    printf("%p, %p, %d\n", pI, &i, i);
    printf("%d, %d, %p\n", sizeof(int*), sizeof(pI), &pI);
    printf("%d, %d, %p\n", sizeof(char*), sizeof(pC), &pC);
    printf("%d, %d, %p\n", sizeof(float*), sizeof(pF), &pF);
    
    return 0;
}

        我们在678行分别定义了 int* char* float* 类型的指针,在第10行通过指针 pI 指向了 i 的地址,再通过第12行的取指针的内容并赋值来达到改变 i 的值。那么我们接下来打印下指针 pI 的地址,i  的地址还有 i 的值分别是什么。还有看下三种不同类型的指针所占的内存大小和地址各是什么,编译结果如下

技术分享图片

        那么我们看到指针 pI 和 i 的地址相同,并且 i 的值已经通过指针成功改变为10。接着我们看到不管是什么类型的指针所占的内存大小都是4,并不是我们之前所认为的 int 为4,char 为1,float 为4啦,它们的地址连续着。说明指针在内存中并没有类型之分,所存储的内存都是在同一个段上。

        我们接下来再来看个传值调用和传址调用。那么在程序中,指针也是变量,因此可以声明指针参数。当一个函数体内部需要改变实参的值,则需要使用指针参数。函数调用时实参值将复制到形参,指针适用于复杂数据类型作为参数的函数中。我们下来利用示例代码进行说明传值调用和传址调用的区别,代码如下

#include <stdio.h>

int swap(int a, int b)
{
    int c = a;
    
    a = b;
    
    b = c;
}

int main()
{
    int aa = 1;
    int bb = 2;
    
    printf("aa = %d, bb = %d\n", aa, bb);
    
    swap(aa, bb);
    
    printf("aa = %d, bb = %d\n", aa, bb);
    
    return 0;
}

        我们想当然是 swap 函数能完成两个数交换的功能,我们来编译下,看看是否能交换呢?

技术分享图片

        结果是这样的,卧槽,是我们搞错了嘛。看来看去觉得程序就该这么写啊,我们再来仔细分析下。我们在第19行只是将变量 aa 和 bb 的值复制给了 swap 函数的实参 a 和 b。在 swap 函数内部确实完成 a 和 b 的值交换,但只是 a 和 b 的值交换了而已。换句话说,这时他两跟变量 aa 和 bb 没啥关系,我们这种就属于传值调用。我们再将 swap 函数改成下面这样呢?看看结果如何

int swap(int* a, int* b)
{
    int c = *a;
    
    *a = *b;
    
    *b = c;
}

        再将 main 函数中第19行改成 swap(&aa, &bb); 我们来看看编译结果如何

技术分享图片

        我们看到加了个 * 号,竟然神奇般改变了 aa 和 bb 的值。感觉很神奇啊,我们仔细分析下,这就是属于利用指针指向变量 aa 和 bb 的地址,然后再通过 * 取地址处的内容再赋值改变。这样就是我们所说的传址调用啦。

        我们下来再来看看一个笔试面试中经常会问到的问题:a> const int* p;b> int const* p;c> int* const p;d> const int* const p 四种有什么区别。我们来一一分析:a> p 可变但它指向的内容不可变;b> p 可变但它指向的内容不可变;c> p 不可变但它所指向的内容是可变的;d> p 和它所指向的内容都是不可变的。我们对待这种问题有个口诀就是:左数右指。什么意思呢?就是当 const 出现在 * 号左边时指针指向的数据为常量,当 const 出现在 *  号右边时指针本身为常量。这样是不是就很好记了呢?反正博主是记住了哈。

        我们下来再来个示例代码对其进行说明,代码如下

#include <stdio.h>

int main()
{
    int i = 0;
    
    const int* p1 = &i;
    int const* p2 = &i;
    int* const p3 = &i;
    const int* const p4 = &i;
    
    *p1 = 1;    // compile error
    p1 = NULL;  // ok
    
    *p2 = 2;    // compile error
    p2 = NULL;  // ok
    
    *p3 = 3;    // ok
    p3 = NULL;  // compile error
    
    *p4 = 4;    // compile error
    p4 = NULL;  // compile error
    
    return 0;
}

        我们看到第12行明显会出错,因为 const 出现在 * 号的左边,左数右指嘛,就是它所指向的内容是不可变的。第15行也是同样的错误。第19行则是因为 p3 是 const 出现在 * 号的右边,所以它本身不可变。p4 前后都有 const,所以第21、22行均会出错。我们来看看分析是否正确呢

技术分享图片

        我们看到结果与我们分析的是一致的,我们以后遇到这种笔试面试题岂不是送分题啦?哈哈,开个玩笑了,其实还是很简单的只需记住口诀就好。我们看看指针是否是那样传说中的难呢?其实也不难的。通过对指针的学习,我们总结如下:1、指针是 C 语言中一种特别的变量;2、指针所保存的值是内存的地址;3、可以通过指针修改内存中的任意地址内容。


        欢迎大家一起来学习 C 语言,可以加我QQ:243343083

C之指针(二十四)

标签:C语言   指针   

原文地址:http://blog.51cto.com/12810168/2104633

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!