C语言中的指针

C语言指针详解

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、什么是指针

二、指针的一些应用

1.指针的定义

2.指针的类型

3.指针的空间中的大小

4.*和&的使用

5.数组和指针

6.野指针、void指针、NULL指针

总结


前言

这次主要介绍指针的知识,通过演示一些简单的应用帮助大家更好的了解指针。

一、什么是指针

指针实际上就是地址,保存地址的那个变量叫做指针变量,指针变量中保存的一定是地址。

二、指针的使用

1.指针的定义

#include <stdio.h>
int main()
{
        int num = 0;
        int* p = &num;
        printf("&num=%p\n",p);
        return 0;
}

这个就是正常情况下的指针的定义,打印出的就是num的地址。

2.指针的类型

定义指针变量的时候需要加上指针类型,指针的类型则决定了对指针进行解引用时访问几个字节,也决定了指针加一时会跳过的字节数,说数组和指针时会看到。

上面示例中指针的类型就是int *类型,而*代表的是指针,那我如何确定指针变量的类型呢?很简单只需要将数据名去掉,剩下的就是它所对应的类型,这么说不明白?来看示例:

#include <stdio.h>
int main()
{
        int num = 0;
        int* p = &num;
        int** pp = &p;
        printf("&num=%p\n",p);
        printf("&p=%p",pp);
        return 0;
}

结果如下:

在这段代码中,p是什么类型的呢?将int* p中的p去掉,就剩下int*,那他就是int类型,将指针p的地址给了pp,将int** p中的变量名p去掉,指针变量pp的类型就是-----int**。记住上面判断指针变量类型的方法。

3.指针的空间中的大小

指针变量也是变量,既然是变量,那就会在内存中分配空间,所以指针变量的大小是多少呢?我直接说明,任何类型的的指针变量的在64位操作系统下是8个字节,在32位操作系统下,4个字节。指针的大小和类型没有关系,可以验证一下:

#include <stdio.h>
int main()
{
        printf("p的大小:%ld\n",sizeof(int*));
        printf("p的大小:%ld\n",sizeof(char*));
        printf("p的大小:%ld\n",sizeof(float*));
        printf("p的大小:%ld\n",sizeof(double*));
        return 0;
}

结果如下:

 可以确定不论何种类型的指针变量都是是占有8个字节的。

4.*和&的使用

*在运算的时候是乘,但在指针这里,一是用来定义指针变量的,二是用来进行解引用操作的;来看一下简单的解引用:

#include <stdio.h>
int main()
{
        int num = 20;
        int* p=&num;
        printf("num的地址:%p\n",p);
        printf("num的值为:%d\n",*p);
        return 0;
}

可以看到所谓解引用就是将指针变量p所保存地址中的值取了出来,知道这个就可以了,接着看后面。

&,这个符号在运算时,指的时按位与 运算符(不了解的可以看一下我之前发过的c语言中的运算符),那么在这里取地址符,scanf(),初始化指针指针的时候经常用到。

5.数组和指针

在介绍数组和指针之前还有东西是需要大家知道的,看示例:

#include <stdio.h>
int main(){       
        int arr[8]={0,1,2,3,4,5,6,7};
        int* p=arr;
        printf("arr=%p\n",arr);
        printf("arr+1%p\n",arr+1);
        printf("&arr+1%p\n",&arr+1);
        printf("sizeof(arr)=%ld\n",sizeof(arr));
        return 0;
}

arr与arr+1之间相差了4个字节,arr的地址也就是arr[0]的地址,我们定义的是int类型的数组,相差4个字节就意味arr+1等价于arr[1] ,没有问题。再看&arr+1,发现打印的地址,和首地址相差了32个字节,刚好是sizeof(arr)这个数组的长度,那我们就得知&arr再进行加1会跨越一整个数组。

小结,&arr和sizeof(arr)这两种情况是代表整个数组。

现在开始看数组和指针,数组的使用离不开指针,都知道数组名就是首元素的地址,既然是地址,我们就可以将指针和数组联系起来,通常我们打印数组中的元素,是使用数组索引进行打印的,那今天看一下指针的用法:

#include <stdio.h>
int main()
{
        int arr[8]={0,1,2,3,4,5,6,7};
        int* p=arr;
        //用数组的长度除一个元素的长度,就是数组元素的个数;
        int length = sizeof(arr)/sizeof(arr[0]);
        for(int i=0;i<length;i++)
        {
                printf("arr[%d]=%-2d",i,arr[i]);
        }
        putchar('\n');
        for(int i=0;i<length;i++)
        {
                printf("arr[%d]=%-2d",i,*(p+i));
        }
        putchar('\n');
        return 0;
}

两种打印的结果一摸一样,使用索引打印大家都会,来看一下使用指针的原理。

 p存放的是数组首元素的地址,即p等价于&arr[0],p+1代表的就是&arr[0]+1,  在之前那个例子中得到的结论是&arr+1代表是地址加32,那现在是&arr[0]+1,代表的便是地址+4,对应的也就是&arr[1],所以p+1等价于&arr[1],再加上解引用,就是指向地址所对应的值了。下面是一个等式帮助理解:

 会一维数组的指针,相信二维甚至多维你们也都将可以轻松拿下了。

6.野指针、void指针、NULL指针

野指针指的是指针中没有存地址的或是随机的无效的地址:

#include <stdio.h>
int main()
{
    int a;//局部变量没有赋初值,值是随机的,包括指针变量。
    int* p;//野指针,没有给变量存放地址,p中的地址是随机的。
}

void*是一种特殊的指针类型,可用于存放任意对象的地址。

#include <stdio.h>
int main()
{
    int data = 100;
    void *p = &data;
    return 0;
}

但因为它没有类型,所以不能用直接用指针操作所指的对象。

NULL指针,#define NULL (void *)0 定义指针的时候,一般会把指针的值初始化为0地址,仅仅用于初始化。0地址用户没有执行权限。直接对0地址操作,系统会提示段错误。

#include <stdio.h>
int main()
{
    int num = 20;
    int* p = NULL;
    p = &num;//一定在p中存一个有效地址,因为NULL,仅仅用于初始化。
}

总结

指针应用非常广泛且灵活,是c的的难点和重点,希望引起重视。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值