今天我们又要认识一下C语言中的一个重点加难点,是什么呢,就是指着,指针在我们以后的编程中会经常遇到,今天我们做一个简单的介绍,以后我们遇到相关文件再继续拓展。

什么是指针

  • 计算机内存是以字节为单位的存储空间,内存的每一个字节都有一个唯一的编号,这个编号就称之为地址。当C程序中定义一个变量的时候,系统就分配一个带有唯一地址的存储单元来存储这个变量,程序对变量的读取操作(变量的引用),实际上是对变量所在存储空间进行写入或者兑读取。
  • 通常我们引用变量的时候是通过变量名来直接引用变量,例如赋值运算b = 66,系统自动将变量名转换成变量的存储位置(即地址),然后再讲数据66放入变量b的存储空间中。这种引用变量的方式称为变量的“直接引用”方式。
  • 此外,C语言中还有另一种称为“间接引用”的方式。它首先将变量A的地址存放在一个变量B(存放地址的变量称之为指针)中,然后通过存放地址的这个变量B来引用变量A。
  • 一个变量的地址称之为该变量的指针。用来存放一个变量地址的变量称为指针变量。当指针变量p的值为某变量的地址的时候,可以说指针变量p指向该变量。

总结:

定义变量的本质:在内存呢中开辟出一块空间,并用一个变量名指向那一块空间。
内存空间的最小单位是字节,每一个字节都有一个自己的编号,这个编号称为地址。
有一种特殊的变量,这种变量专门存变量的地址,我们称之为指针变量,一般也称为指针。

指针的基本使用方式

  • 指针的使用一般分为三步:

    • 定义指针变量
    • 给指针变量赋值
    • 指针解引用
  • 整个过程中需要使用到两个运算符:&和*

定义指针变量

定义指针变量的格式为:
类型名 *指针变量名;

int* p1;
char * p2;

注:

变量前面的*是一个说明符,用来说明该变量是指针变量,这个*是不能省略的,但是这个*不是变量名的一部分。
类型名表示该指针指向的变量类型,而且该指针只能指向该类型变量。

给指针变量赋值

之前在我们使用scanf_s用到取地址符&,这里我们也会用到这个符号来取一个变量的地址赋值给指针。

int nNum = 100;
int *p;
p = &nNum;//指针指向了变量nNum

我们也可以在指针初始化的时候对指针进行赋初值:

int nNumA;
char cChA;
int *p1 = &nNumA;
char *p2 = &cChA;

这里两个指针在初始化的时候就进行了赋值,p1赋值的是int型变量nNumA的地址,p2赋值的是char型变量cChA的地址。

指针变量的引用

这里我们需要用到符号有两个,一个是指针运算符*,另一个是取地址符&

int a = 10;
int *p = 0;
p = &a;
int temp = *p;
//此时temp被赋值为10,也就相当于temp = a;

*p = 20;
//修改的是指针指向变量的内容,也就是修改a的内容,相当于a = 20;

注:

指针变量是用来存放地址的,所以不要给指针赋值常数值,但是赋值0相当于将指针指向NULL。
例如:*p = 10000;
指针没有指向一个确定的地址之前,不要对他的所指向的内容进行操作。
例如:int nNum = 5;int *p;*p = nNum;

示例:

int main()
{
    //1 定义指针变量
    int* p1 = NULL;

    char * p2  = NULL;

    int nNum1 =100;
    int nNum2 = 0;
    char cCh1 = 'm';
    //2 给指针变量赋值
    p1 = &nNum1;//指针存储了谁的地址,我们就说指针指向了谁

    p2 = &cCh1;//存储了b的地址,指针指向了变量b


    //3 解引用
    *p1 = 10;
    *p2 = 'm';
    printf("%d", nNum1);

    printf("%c ", *p2);
    printf("%c", cCh1);
    //4 修改指针变量
    p1 = &nNum2;
    *p1 = 300;
    return 0;
}

指针与函数传参

指针是间接引用的,我么可以利用这一特性来进行参数传递,从而使得参数在函数内部的改变可以形象到函数外部。

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

void main()
{
    int a = 10;
    int b = 20;
    swap(a,b);
    printf("%d,%d",a,b);
}

通过输出的结果我们可以看出来,这两个变量的值经没有改变。

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

void main()
{
    int a = 10,b = 20;
    swap(&a,&b);
    printf("%d,%d",a,b);
}

在上面的这个例子中,我们通过向函数中传递了两个变量的地址,在函数中以指针的方式接受了两个变量的地址,通过两个变量的地址,我们可以找到两个变量的存储内容的空间,通过指针修改了两个变量的内容。
但是这中方式并没有使用形参修改实参的内容,因为在上面的例子中,实参是两个变量的地址,但是最终修改的不是两个变量的地址。

指针的运算与一维数组

指针是可以有数学运算的,但是它的运算和它的类型有关。

int a = 100;
int *p = &a;
p+1;
//这个时候进行p+1,不是对p指向的a的值加1,也不是p指向的地址加1,
//而是将指针指向的位置向后移动一个int,
//p+1计算方式为:p指向的的地址+sizeof(指针类型,这里是int),就相当于&a+4。
//所以p+1实际上地址加了4。

short b = 200;
short *p1 = &b;
*p1++;
//通过上面的计算方式,我们可以知道这里是地址加了2。

指针运算的方式设计为这样主要是为了数据访问的便利性,我们可以看一下指针和数组的操作。

int Arr[5] = {0,1,2,3,4};
int *p = Arr;    //数组名就是数组首元素的地址
printf("%d",p[0]);//和数组中的Arr[0]一样
pritnf("%d",p[4]);

//使用指针的方式操作数组中的数据
printf("%d",*(Arr+0));//和p+0以及Arr[0]一样
printf("%d",*(Arr+4));

一维数组的数组名就是地址,并且一维数组名这个地址也是有类型的,就是一级指针类型。

总结

指针只是一个变量,这个变量是用来存放地址的。
指针复杂的地方在于:指针有多种多样类型。

最后修改:2020 年 08 月 26 日
如果觉得我的文章对你有用,请随意赞赏