C语言自学完备手册(27)——指针(1)

版权声明: https://blog.csdn.net/lfdfhl/article/details/83105627

自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理


探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制


Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南


讲给Android程序员看的前端系列教程(图文版)
讲给Android程序员看的前端系列教程(视频版)
Android程序员C语言自学完备手册


版权声明


从本小结开始学习指针。

取地址运算符

利用&可以获取变量(有时也泛称对象)在内存中的地址。请看如下示例:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int x;
    double y;
    int z[3];
    printf("x的地址是%p\n",&x);
    printf("y的地址是%p\n",&y);
    printf("z的地址是%p\n",&z);
    return 0;
}

结果如下:

x的地址是0060FF0C
y的地址是0060FF00
z的地址是0060FEF4

在该示例中通过了&获取了各变量在内存中的地址。更确切地说:&获取了变量在内存中的首地址!还有一个小细节需要留意:在printf( )函数中使用的是%p来表示打印变量地址,p是单词pointer的缩写。

单纯地使用&获取变量在内存中的地址没有太大的实际意义,更多的是将其与指针联合在一起使用。


指针概述

指针(pointer)堪称C语言的灵魂,由此开始,我们正式进入指针的学习。

在C语言中利用*声明指针。例如:

int *p;

该语句有以下几重含义:

  1. p是一个指针,它是int*型指针
  2. 该指针指向一个int类型变量
  3. 该指针中所存储的是int类型变量在内存中的地址

核心小结:

1 指针的声明如下:Type *指针名,该指针的类型是Type*型;或者说该指针是Type*型指针
2 一般来说,Type*型指针不会指向Type型以外的对象。
3 指针指向的是对象在内存中的首地址!

接下来初始化该指针:

int *p;
int number=9527;
p=&number;

好了,有了刚才的基础知识,我们来看一个简单的示例,代码如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *p;
    int number=9527;
    p=&number;
    printf("p在内存中的地址是%p\n",&p);
    printf("number在内存中的地址是%p\n",&number);
    printf("number在内存中的地址是%p\n",p);
    printf("number=%d\n",number);
    printf("number=%d\n",*p);
    puts("----------------");
    number=999;
    printf("number=%d\n",number);
    printf("number=%d\n",*p);
    puts("----------------");
    *p=888;
    printf("number=%d\n",number);
    printf("number=%d\n",*p);
    return 0;
}


在该示例中指针p指向了int类型的变量number。所以,p中所存的正是变量number在内存中的地址。故,可以通过&number和p这两种方式得到number在内存中的地址。我们若想获取或者修改number的值,可通过number和*p两种方式进行。也可以通俗地理解为:*p是number的别名,两者指向了同一个内存区域。

结果如下:

在这里插入图片描述

示例小结

在本示例中存在以下对等关系

  • &number等价于p
  • number等价于*p

练习题

练习题1:将1—100中的数字的值翻倍显示

需求很简单,实现代码如下:

#include <stdio.h>
#include <stdlib.h>

void changeNumber(int number){
    if(number>=0&&number<=100){
        number=number*2;
    }
}

int main()
{
    int number=17;
    printf("修改前number=%d\n",number);
    changeNumber(number);
    printf("修改后number=%d\n",number);
    return 0;
}

结果如下:

修改前number=17
修改后number=17

在该示例中并没有成功的改变number的值。因为这种传递方式是值传递,实参和形参彼此独立,不能够相互影响。所以,我们可以用指针来解决该问题。

#include <stdio.h>
#include <stdlib.h>

void changeNumber(int *p){
    if(*p>=0&&*p<=100){
        *p=*p*2;
    }
}

int main()
{
    int number=17;
    printf("修改前number=%d\n",number);
    int *q=&number;
    changeNumber(q);
    printf("修改后number=%d\n",number);
    return 0;
}

在该示例中将指针作为参数传递。修改指针的值就等同于修改原来的值,即代码第6行。这样就避免了在值传递过程中带来的不便。

结果如下:

修改前number=17
修改后number=34

在这儿,我们初步领略了指针的魅力,继续我们的练习。

练习题2:在一个函数中计算两个数的和与差

#include <stdio.h>
#include <stdlib.h>

void getSumAndDiff(int a,int b,int *sum,int *diff){
    *sum=a+b;
    if(a>b){
        *diff=a-b;
    }else{
        *diff=b-a;
    }
}
int main()
{
    int a;
    int b;
    int sum=0;
    int diff=0;
    int *s=&sum;
    int *d=&diff;
    puts("请您输入两个整数");
    printf("请输入第一个整数:");
    scanf("%d",&a);
    printf("请输入第二个整数:");
    scanf("%d",&b);
    getSumAndDiff(a,b,s,d);
    printf("两个数的和=%d,两个数的差=%d",sum,diff);
    return 0;
}

结果如下:

请您输入两个整数
请输入第一个整数:5
请输入第二个整数:8
两个数的和=13,两个数的差=3
Process returned 0 (0x0) execution time : 5.529 s
Press any key to continue.

练习题3:交换两个数

#include <stdio.h>
#include <stdlib.h>

void swapNumber(int *a,int *b){
    int temp=*a;
    *a=*b;
    *b=temp;
}

int main()
{
    int a=4;
    int b=9;
    int *p=&a;
    int *q=&b;
    printf("交换前a=%d,b=%d\n",a,b);
    swapNumber(p,q);
    printf("交换后a=%d,b=%d\n",a,b);
    return 0;
}

结果如下:

交换前a=4,b=9
交换后a=9,b=4

在刚才的示例中创建了两个指针p和q并将两者作为swapNumber( )方法的输入参数。其实,我们也可以不定义这两个指针,直接将&a和&b作为swapNumber( )方法的输入参数;代码如下:

#include <stdio.h>
#include <stdlib.h>

void swapNumber(int *a,int *b){
    int temp=*a;
    *a=*b;
    *b=temp;
}

int main()
{
    int a=4;
    int b=9;
    printf("交换前a=%d,b=%d\n",a,b);
    swapNumber(&a,&b);
    printf("交换后a=%d,b=%d\n",a,b);
    return 0;
}


空指针

空指针(null pointer)是一种非常特殊的指针,它表示“什么也不指向”的指针


scanf( )函数与指针

我们通常在使用scanf( )函数时都会在变量名前加上一个特殊符号&,例如:

int no;
scanf("%d",&no);

该代码片段表示:接收键盘输入的整数值,并将该值赋给变量i。

类似的代码已经写过很多次了,我们可能不禁要问:为什么通常在使用scanf( )函数时会在变量名前加上一个符号&?因为scanf( )函数要往变量里写入数值,所以它必须知道该变量的在内存中的地址。至于该变量里是否已经存在值,存的是什么值,scanf( )是不管的,它只管把键盘输入的值存入该变量!

顺便地我们再回过头来看看printf( )函数,该函数的作用是输出变量里的数值。所以它只关注变量的值是多少,至于该变量在内存的地址它是不理会的。

从本质上而言:scanf( )函数用于写数据,printf( )函数用于读数据。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lfdfhl/article/details/83105627