C语言之指针的使用

1、内存地址:

  • 每个地址占一个字节,系统为了区分每一个字节,给它们逐一编号,称为内存地址,简称地址。
  • 字节为内存的容量单位,一个字节8位。

2、基地址

  • 单字节数据:单个字节数据而言,其地址就是基地址;
  • 多个字节数据:多个字节数据而言,其编号最小的地址是基地址;

3、取地址(&):

  • 每个变量都有一个内存,都可以通过&来获取其地址信息;
int a=100;
printf("%p\n",&a);

输出:
a的地址

4、指针的定义:

  • 指针变量存放的数据类型是指针变量的地址;
  • int *p1;         //用于存储 int型数据的地址,p1被称为int型指针;
  • char *p2;     //用于存储char型数据的地址,p2被称为char型指针;
  • double *p3; //用于存储double型数据的地址,p3被称为double型指针;

5、指针的赋值:

#include <stdio.h>
int main()
{
    int a=100;
    int d=11;
    int e=111;
    int b[4]={1,2,3,4};
    char c='a';
       
    char *p=&c;
    int *p1=&a;         //p1指向a的地址

    int *p2=&b[3];
    int *p2_1=b;        //将数组b的首元素地址赋给指针p2_1

    int *p3;
    p3=&a;
    
    int *p4=&d;
    *p4=e;              //指针的索引,将e的值赋给指针p4所指向的变量d

    printf("%c\n",*p);      //p指向c的地址,在解引用a的值
    printf("%p\n",p1);     
    printf("%d\n",*p2);
    printf("%d\n",*p2_1);
    printf("%d\n",*p3);
    printf("%d\n",*p4);
    return 0;
}

输出:

6、特殊指针:

①野指针:指向一个未知区域的指针,称为野指针。野指针是危险的

危险:

  • :引用野指针,相当于访问了非法的内存,常常会导致段错误(segmentation fault);
  • :引用野指针,可能会破坏系统的关键数据,导致系统崩溃等严重后果;

产生原因:

  • 指针定义之后,未初始化;
  • 指针所指向的内存,被系统回收;
  • 指针越界;

如何防止:

  • 指针定义时,及时初始化(不明确时指向NULL);
  • 绝不引用已被系统回收的内存(回收后令指针指向NULL);
  • 确认所申请的内存边界,谨防越界;

7、空指针(NULL):

空指针是保存零地址的指针;

为了避免野指针,通常可将指针指向零地址;

int *p=NULL;        //指针指向零地址;

8、指针的运算:

  • 两个指针相加没有意义,两个指针相减可以得到两个指针地址的偏移量;
int a,b;
int *p=&a;
int *q=&b;
q+p;    //得到一个新地址,但没有实际意义
q-p;    //得到两个地址的距离
  • 指针加法(自增或加上某个数值)意味着地址向上移动若干个目标(数据类型的字节单位<步长>)
  • 指针减法(自减或减去某个数值)意味着地址向下移动若干个目标(数据类型的字节单位<步长>)
#include <stdio.h>
int main()
{
    int a[10]={1,2,3,4,5,6,7};
    int *p=&a[0];               //指针p为数组a[0]的地址
    int *p1=&a[5];              
    printf("p:%d\n",*(p+1));    //指针p指向a[1]的地址在解引用得a[1]的值
    printf("p1:%d\n",*(p1-2));
    return 0;
}

输出结果:

9、指针语法:

  • 任意的指针,不管有多复杂,其定义都由两部分组成;
  • 第1部分:指针所指向的数据类型,可以是任意的类型
  • 第2部分:指针的名字
char    (*p1);    //第2部分 :* p1;第1部分:char;        字符指针
char   *(*p2);    //第2部分 :* p2;第1部分:char *;      指向指针的指针(二级指针)
char  **(*p3);    //第2部分 :* p3;第1部分:char **; 三级字符指针
char (*p4)[3];    //第2部分 :* p4;第1部分:char [3];数组指针
char   *p5[3];    //第2部分 :p5[3];第1部分:char *;数组存储的都是指针地址,指针数组
char (*p6)(int ,char );    //第2部分 :* p5;第1部分:char(int,float);函数指针

①一维数组,内存地址连续,数组名可当指针使用;

int a[10]={1,2,3,4,5,6};
int *p=a;
printf("p:%d\n",p[2]);

输出:
3

指针与数组从键盘获取字符:

char *p;        
char *p1;
p=calloc(1,20);        //申请堆地址1块大小为20的内存
p1=calloc(1,20);       //不申请地址会段错误
scanf("%s",p);
scanf("%s",p1);


char str1[20];
char sre2[20];
scanf("%s",str1);
scanf("%s",str2);

 

② 二位数组的指针

#include <stdio.h>
int main()
{
    int a[3][3]={1,2,3,4,5,6,7};
    int (*p)[3]=a;
    int *p1=a[0];
    printf("p:%d  %d\n",*p[1],*(*a+1));
    printf("p1:%d\n",*(p1+2));
    return 0;
}

输出:
p:4  2
p1:3

③char型指针:

        char型指针实质上跟别的类型的指针并无本质区别,但由于C语言中的字符串以字符数组的方式存储,而数组在大多数场合又会表现为指针,因此字符串在绝大多数场合就表现为char型指针。

#include <stdio.h>
int main()
{
    char *p="hello";        //只能读取
    //*p='x';不可以对p进行值修改
    printf("p:%c\n",*p);
    printf("p:%c\n",*(p+1));
    printf("p:%c\n",p[2]);
}

④多级指针:

  • 如果一个指针变量p1存储的地址,是另一个普通变量a的地址,那么称p1为一级指针
  • 如果一个指针变量p2存储的地址,是指针变量p1的地址,那么称p2为二级指针
  • 如果一个指针变量p3存储的地址,是指针变量p2的地址,那么称p3为三级指针
  • 以此类推,p2、p3等指针被称为多级指针

示例:

int a=100;
int *p=&a;        //一级指针,指向普通变量
int **p1=&p;      //二级指针
int ***p2=&p1;    //三级指针

⑤void型万能指针:

  • 概念:无法明确指针所指向的数据类型时,可以将指针定义为void型指针
  • 要点:

        a.void 型指针无法直接索引目标,必须将其转换为一种具体类型的指针方可索引目标

        b.void 型指针无法进行加减法运算

  • void关键字的三个作用:

        a.修饰指针,表示指针指向一个类型未知的数据。

        b.修饰函数参数列表,表示函数不接收任何参数。

        c.修饰函数返回类型,表示函数不返回任何数据。

⑥const型指针:

  • const型指针有两种形式:
  • ①常指针

        常指针:const修饰指针本身,表示指针变量本身无法修改。

char a;
char *const p=&a;    //常指针:指针指向的目标无法修改,定义常指针时要赋初始值;
char a1;
//p=&a1;             //不能在给p赋新的地址
*p='A';              //可以修改值
printf("%c\n",*p);   //常指针除了不能修改指向目标,其他与普通指针用法相同 
printf("%c\n",a);
  • ②常目标指针

        常目标指针:const修饰指针的目标,表示无法通过该指针修改其目标。

char ch;
char const *p=&ch;    //常目标指针:指针对其指向的目标只读
char ch1;
*p=ch1;      //可以修改指向  
//*p='A';    //不能修改目标内容

⑦函数指针:

  • 概念:指向函数的指针,称为函数指针。
  • 特点:函数指针跟普通指针本质上并无区别,只是在取址和索引时,取址符和星号均可省略

示例:

void (*func)(int,char);    //指针函数func的参数有一个整形一个字符,没有返回值
  • 要点:

        a.函数指针是一类专门用来指向某种类型函数的指针。

        b.函数的类型不同,所需要的函数指针也不同(函数指针的类型必须和其指向的函数的类型(返回值及形参列表类型)一致)。

        c.函数的类型,与普通变量的类型判定一致,即去除声明语句中的标识符之后所剩的语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

biubiuboomy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值