C的精髓——指针

本文深入探讨了C语言中的指针概念,包括内存、地址与指针的关系,指针变量和变量指针的区别,二级及多级指针的使用,指针数组与数组指针的不同,以及指针函数和函数指针的应用。

指针是一种数据类型,属于这种类型的变量,为指针变量。下面介绍主要是针对指针不同的用法。

目录

1、内存、地址与指针

2、指针变量和变量指针

3、 二级指针和多级指针

4、指针数组和数组指针

        5、指针函数和函数指针


  • 内存、地址与指针

在计算机的内存里,一个字节就是一个内存单元,不同的数据类型在不同的操作系统下所占的内存带能源是不一样的。比如

不同操作系统
 intlongchar*
32位编译器444
64位编译器488

为了正确的访问这些内存,必须给每个内存单元编上号。在前面提过,内存就像是宿舍楼,每个宿舍都有门牌号,方便访问。这个门牌号就是地址,也就是指针。指针里面存的便是地址。我们需要访问谁,或者指向谁,里面就是谁在内存里的地址。指针是一个常量。我们声明和定义指针的时候,都是以一个变量被赋值的形式(后面介绍)。我们常把指针变量当作指针。下面的图来有助于理解。

  • 指针变量和变量指针

  1. 指针变量:在C语言中允许一个变量来存放某个变量的地址,这个变量就是指针变量。我们简称指针。任何指针都是4字节
  2. 变量指针:变量的地址。
  • 下面具体的例子来理解指针变量的声明和定义。
//C语言

    int num=0;           //这是一个变量:声明
    int* p=#          //这是一个指针变量。指向num的地址。:初始化
    //解引用
    *p  = 0;//解引用的概念就是说把指针指向的地址的数据取出来
  • 指针变量作为函数参数
//C语言
//交换两个数的值
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
void swap(int* p1,int*p2) {
	int temp = *p1;         //这里不能声明int* temp
	*p1 = *p2;		//因为不知道*temp所指向的内存单元是什么。
	*p2 = temp;		//随意赋值可能会影响系统的正常工作
}
void main() {
	int num1 = 0;
	int num2 = 2;
	int* p1 = &num1;
	int* p2 = &num2;
	scanf("%d %d",&num1,&num2);
	swap(p1,p2);
	printf("%d %d\n",num1,num2);
	system("pause");
}
  •  二级指针和多级指针

概念:(1)指向指针的指针,称为二级指针

           (2)指针的指针的指针...称为多级指针

声明方式:

类型名+ ** + 指针名(二级指针)

//C语言

int** p;

char** p;

理解:

多级指针就是多几个“  *  ”。首先任何值都有地址 ,一级指针的值虽然是地址,但这个地址做为一个值亦需要空间来存放,是空间就具有地址 ,这就是存放地址这一值的空间所具有的地址,所以任何级指针都是指向的地址而已,如果实在不好理解,可以这样借助一个C语言的关键字——typedef。作用是为一种数据类型定义一个新名字。

//C语言
//下面解释怎么理解二级以上的指针,拿二级指针做例子。

main(){

    int num = 10;
    int* p = &num;
    int** pt = &p;

}

//typedef    关键字

main(){

    typedef int* int_p;
    int num = 10;
    int_p p = &num;
    intP pt = &p;

}

//是不是还是一级指针?所以多少级的都不怕。再有,太多级了。我们也不用啊
  • 指针数组和数组指针

  • 指针数组:指针指向整个数组,当指针+1,将会跨越整个数组

声明格式:

类型名 + * + 数组名[ 个数 ]

 

  • 数组指针:数组存的是指针类型的数据

声明格式:

 类型名 +( * 数组名) [ 个数 ]

 

//C语言
//数组指针

//  定义 int (*p)[n];
//  (1)优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,执行p+1时,p要//  跨过n个整型数据的长度。 
//  (2)如要将二维数组赋给一指针

int a[3][4];
    int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
    p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
    p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

//指针数组
//定义 int *p[n];
//[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。
  • 指针函数和函数指针

当学习了指针数组和数组指针,对于两者的区别和理解便轻松许多。

  • 指针函数:当一个函数声明返回一个指针的时候,实际就是返回一个地址给调用对象。

声明格式:

类型名 + * + 函数名 (参数)

  • 函数指针:其实就是函数的地址,可以通过地址来调用函数。

声明格式:

类型名 + (*  函数名 )(参数)

下面来通过代码来帮助理解。

//C语言

//指针函数
//因为返回的是一个地址,所以指针函数一般用int 定义

int* get_adress()

int* to_function(int num)

//函数指针

void (*p_f)()

这里 说明一下  void*  这是一个非常重要的定义。定义指针变量时,不会知道其指针类型。就像知道门牌号,但不知道其房间的大小,所以它可以赋值成任何一个指针,它就是一个万金油的存在。所以它的类型会在复制之后知晓。下面看一个例子

//C语言


int num = 2018;
int* p = &num;

void* vp = p;

这里写一个函数指针的例子。主要用于回调函数,回调函数的重要概念已在前面记录。回调函数

//C语言

viod (*p_fun)();//定义一个函数指针

void fun(){
    printf("函数指针\n"):
}
main()
{
    p_fun=fun;
    (*p_fun)();
}

指针的介绍到这儿,后面的学习会更加深入的了解指针,这是C语言的王牌,熟练的掌握便是质的提升!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值