C语言-指针

        C语言中,内存单元的地址成为指针,专门用来存放地址的变量,有时对地址,指针和指针变量不区分,统称指针。

1、指针变量的说明:

        一般形式:<存储类型>  <数据类型> *<指针变量名>

char *pName;
int a;

        指针的存储类型是指针变量本身存储类型

        指针说明时指定的数据类型不是指针变量的数据类型,而是指针目标的数据类型,简称为指针的数据类型

        指针在说明的同时,也可以被赋值,叫做指针的初始化

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

int main()

    {
        int a = 3;
        int *pa;

        pa= &a;


        printf("%x %d %p",pa,*pa,a);

    }

  结果:

 2、指针的赋值运算指得是通过赋值运算符指针变量送一个地址
    向一个指针变量赋值时,送的值通常都是地址常量,不能是普通的整数(除了零以外)

1、把一个普通的变量的地址给一个具有同数据类型的指针

double x = 15,*px;
    px = &x;

2、把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量

float a,*px,*py;
px = &a;
py = px;

3、把一个数组的地址赋给具有相同数据类型的指针

int a[20], *pa;
pa = a //等价于 pa = &a[0]
3、 指针运算

        指针运算是以指针变量所存放的低质量作为运算量而进行的运算

        指针运算的实质是地址的运算

        指针运算的种类有限,他只能进行赋值运算、算术运算和关系运算

        不同数据类型的两个指针实行加减整数运算是没有意义的

运算符计算形式意义
+px+n指针向地址大的方向移动n个数据
-px-n指针向地址小的方向移动n个数据
++px++,++px指针向地址大的方向移动一个数据
--px--,--px指针向地址小的方向移动一个数据
.px.py两个指针之间相隔数据元数的个数
px+n表示的实际位置的地址量是:
    (px)+sizeof(px的类型)*n

px-n表示的实际位置的地址量是:
    (px)-sizeof(px的类型)*n

实验:pa-3: 

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

int main()

    {
        int a[5] ={1,2,3,4,5} ;
        int *pa ,*pb,n;

        pa= &a[4];
        pb = pa - 3;
        //pb=&a[3];  //指向特定的时候要加地址符

        n = pb-pa;
        printf("%d %d %d %d",pa,*pa,*pb,pb);

    }

结果:打印的分别是a[4]的地址即pa,a[4]即*pa,向前移动了3个数据即a[1]=*pb=2,a[1]的地址。

 

实验:pa+2:

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

int main()

    {
        int a[5] ={1,2,3,4,5} ;
        int *pa ,*pb,n;

        pa= a; //实际是将a[0]赋值给了pa
        pb = pa + 2;
        //pb=&a[3];  //指向特定的时候要加地址符

        n = pb-pa;
        printf("%d %d %d %d",pa,*pa,*pb,pb);

    }

结果:和上面同理,向后移动了2个数据。

 

4、指针数组

        p=a是将a[0]的地址给p其中想访问别的数组元素就可以移动指针的位置,*pi进行取地址就可以。

  实验: 使用字符数组反序存放

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

int main()

    {
        int a[] ={1,2,3,4,5} ;
        int b[]={0};
        int *pa ,*pb,n,i,j;

        n = sizeof(a)/sizeof(int);

        pa = a; //实际是将a[0]赋值给了pa
        pb = b;

        for(i= 0;i<n;i++)
        {
            //printf("%d\n",pa[i]);
            pb[j]=pa[n-i-1];
            printf("%d",pb[j]);


        }

    }

        结果:

5、指针和二维数组

           二维数组名代表数组的起始地址,数组名加一,移动一行元素,因此二维数组名被称为行地址。

如果对a[i]进行加减则是只移动单个元素。  

       实验:使用行指针遍历二维数组中的每一个元素

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

int main()

    {
     int a[3][2]={{1,2},{3,4},{5,6}};
     int *p[2],i,n,k=0;
     
    for(i=0;i<=2;i++)
    {
        p[i]=a[i];

        n=*p[i]+*(p[i]+1);
        //k=k+n;
        printf("%d %d\n",*p[i],*(p[i]+1));

    }

        //printf("%d",k);
    }

结果:

6、字符指针和字符串
        C语言通过使用字符数组来处理字符串
        通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符有着
        密切关系,他也被用来处理字符串。
        初始化字符指针是把内存中字符串的首地址赋予指针,并不是把该字符串复制到指针
        中。
char str[] = "Hello world";
char *p = str;

        在c语言中,当一个字符指针指向一个字符串常量时,不能修改指针的对象的值。

char *p = "Hello world";
*p = 'h'; 

实验:使用两个字符串数组实现字符串函数的连接功能:

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

int main()

    {
        int a[3][2] ={{1,2},{3,4},{5,6}};
        char ch[100]="welcome";
        char *p="hello world";
        int i=0;
        while(ch[i]!='\0')
        {
            i++;
        }
        while(*p!='\0')
        {
            *(ch+i)=*p;
            p++;
            i++;
        }
        *(ch+i)=*p;
        puts(ch);
        puts(p);

    }
7、 指针数组
        所谓指针数组是指由若干个具有相同存储类型和数据类型的指针变量构成的集合
        指针数组的一般说明形式:
        <存储类型 > <数据类型> *<指针数组名> [<大小>]
        指针数组名表示该指针数组的起始地址
        声明一个指针数组
double *pa2,a[2][3]

        把一维数组a[0]和a[1]的首地址分别赋予指针变量数组的元数pa[0]和pa[1];

pa[0] = a[0]; //等价于pa[0] = &a[0][0]
pa[1] = a[1]; //等价于pa[1] = &a[1][0]

        此时pa[0]指向了一维数组a[0]的第一个元素,而pa[1]指向了一维数组a[1]的第一个元素。

实验:将二级数组的所有的值进行求和

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

int main()

    {
     int a[3][2]={{1,2},{3,4},{5,6}};
     int *p[2],i,n,k=0;
     //p[0]=a[0];
     //p[1]=a[1];
     //p[2]=a[2];
    for(i=0;i<=2;i++)
    {
        p[i]=a[i];

        n=*p[i]+*(p[i]+1);
        k=k+n;
        printf("%d %d\n",*p[i],*(p[i]+1));

    }

        printf("%d",k);
    }

结果:

7、多级指针
多级指针的定义
        把一个指向指针变量的指针变量,称为指针变量 ,        对于指向处理数据的指针变量称为一级指针变量,简称一级指针。
        把指向一级指针变量的指针变量称为二级指针变量,简称二级指针。
二级指针变量的说明形式如下:
<存储类型> <数据类型> **<指针名>
7.1、多级指针的运算
1. 指针变量+1,是向地址大的方向移动一个目标数据。同理,多级指针运算也是以其目标变量为单位进行偏移
2. 比如, int **p; p+1 移动一个int * 变量所占的内存空间。
#include<stdlib.h>

int main()

    {
        int i,n;
    int *p[5]={1,2,3,4,5};

     n=sizeof(p)/sizeof(char*);

    int  **pa;
     pa=p;

    printf("%p %p",*p,*pa+1);


    }

结果:

7.2、 多级指针和指针数组
        指针数组也可也用另外一个指针来处理。
例如: 有一个一维字符指针数组 ps[5]
char  *ps[5]  = {"Beijing","Fuzhou","Xiamen","XiAn","ShangHai"};

实验:使用二级指针将指针数组里的元素全部输出:

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

int main()

    {
        int i,n;
     char *p[5]={"Beijing","Fuzhou","Xiamen","XiAn","ShangHai"};

     n=sizeof(p)/sizeof(char*);

     char **pa;
     pa=p;

    while(i<n)
    {
        printf("%s\n",*(pa+i) );
        i++;

    }


    }

结果:

8、void指针
        void指针是一种不确定数据类型的指针变量,它可以通过强转类型转换让该变量指向任何
数据类型的变量。

        一般形式为: void *<指针变量名称>

        对于void指针,在没有强制转换类型之前,不能进行任何指针的算术运算。

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

int main()

    {
     int n,i,*q;
     int a[5]={1,2,3,4,5};
     
     void *p;
     
     p=a;
     
     q=(int*)p;
     
     n=sizeof(a)/sizeof(int);

     for(i=0;i<n;i++)
     {
         printf("%d ",*(q+i));
     }


    }

结果:

9、const指针
常量化变量的值
一般说明形式如下:
const <数据类型 > 变量名 =[<表达式>];
常量化变量是为了使得变量的值不能修改
变量有const修饰时,若想用指针间接访问变量,指针也要有const修饰
9.1、常量化指针目标表达式
一般说明形式如下:

        

const <数据类型> *<指针变量名称> [= <指针运算表达式>];
    常量化指针目标限制通过指针改变其目标的数值
    但是指针变量存储的地址可以修改
9.2、常量化指针变量及其目标表达式
一般说明形式如下:
const <数据类型>* const <指针变量名> = <指针运算表达式>
    常量化指针目标是限制通过指针改变其目标的数值
    但是<指针变量>存储的地址值可以修改
9.3、常量化指针变量

一般说明形式

<数据类型> * const <指针变量名称> [<指针运算表达式>]
    使得<指针变量>存储的地址值不能修改。
    但可以通过*<指针变量名称> 可以修改所指向变量的数值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值