C语言-指针

一.指针的含义

  • 指针即内存地址

  • 指针变量 即 存储内存地址的变量

  • 内存地址

    • 程序当运行起来,会被操作系统加载内存中,形成内存映像(内存空间)

    • 对内存空间进行编号 (0x0 0x1 0x2 ... )

    • 内存编号 (整数,%p 十六进制的整数)

 

二.取址定位符-&

  • 获取变量的内存地址(内存编号)

  • 可以使用%p来进行格式化输出

  • &操作数必须是标识符

    • 变量名

    • 数组名

    • 函数名

scanf("%d",&num);   //&num 取址
  • 取址运算符得到是内存地址

三.指针变量

需要保存内存地址,需要定义指针变量

        1.定义

TYPE * pname;

TYPE *    是表示一个完整的类型,即指针类型

TYPE -  pname指针变量所存储了一个内存地址    TYPE表示内存地址中的数据为TYPE类型
*    -  说明是指针变量
TYPE *  说明地址(指针)的类型为  TYPE *


TYPE *p1,*p2;   //定义两个指针变量p1,p2
TYPE *px,py;    //px类型为TYPE*,  py类型为TYPE


在定义指针变量时  TYPE 至关重要,决定了解引用时   
    *p 能够取多少个字节的数据    sizeof(TYPE)

        2.初始化

int *p = NULL;             //可以   任意类型的指针变量都可以用NULL来初始

#define NULL  ((void *)0x0)

int *pn;                  //没有初始化    野指针    野指针不能解引用
int num = 0;
pn = #                //对指针变量进行赋值   pn存储了&num这个值(内存地址)

int *pm = #           //定义指针变量直接初始化

        3.赋值 和 解引用 赋值

int a = 10,b = 20;

int *pa = &a;    //定义指针变量 存储&a    
//间接修改a的值   指针的意义  不直接通过变量名修改变量的值,而是通过内存地址
*pa = 1024;      //pa == &a    *pa  ==  *&a        *&a = 1024    a=1024

pa = &b;         //对指针变量pa进行赋值   pa存储&b    
*pa = 9527;      //pa指向了b     pa == &b     *&b = 9527    b=9527

        4.解引用

*内存地址                  即获取内存地址中的数据
*指针变量                  指针变量的值就是内存地址
int num = 0x12345678;
char *pc = (char *)#
int *pi = # 
//pc 的值  和 pi的值 相等 
printf("%#X %#X\n",*pc,*pi);  //对pc和pi解引用  结果不一样
//指针变量pc和pi的类型不一样   char *   int * 
//TYPE * p = &x;    在对p进行解引用时 获取了 sizeof(TYPE)个字节的数据 
  • 指针变量必须要有明确的指向,才能解引用         

        5.取址&和解引用*是一对可逆的过程

&*a           ===   a
*&p           ===   p

&arr[0]   ==  &*(arr+0)   ==  &*arr ==  arr

四.空指针/野指针/万能指针

        空指针

                NULL

        野指针

                指针指向不确定 指针未初始化

                野指针不能直接解引用

        万能指针(void *)

                内存地址就一编号 整数

                任意类型的指针都可以隐式转换为 void *

                指针的通用类型

                void *类型的指针变量,不能解引用

五.指针算术运算

指针 + 1           即内存偏移   向后偏移1个单位的内存
TYPE *p = &x;
p + 1             偏移了 sizeof(TYPE) 字节大小的内存

指针 - 1           向前偏移1个单位的内存

++p;      //p = p + 1;   p保存偏移1个单位之后的内存​--p;      //p = p - 1;

*p++;     

两个指针可以相减(同类型)         得到偏移元素的个数

六.指针与[]闭合

ArrayName[index]    ==    *(ArrayName+index)    == *(index+ArrayName)
index[ArrayName]

下标[]运算,本质上 指针偏移解引用

数组名 本质 是 首元素的内存地址

*arr == arr[0]

*(arr+i) == arr[i]

七.二级指针

指针变量的内存地址

int num = 1024;
int *p = #    //p变量   p存储内存地址  同时它自己也有内存地址

int **pp = &p;    //p类型为int *     &p类型为   int **
pp    ==   &p
*pp   ==    *&p  ==  p  ==  &num
**pp  ==  *p   ==  *&num  == num

int x = 10;
*pp = &x;    //改变的是啥   改变了p的值 
**pp = 8527; //改变的是啥   改变了x的值

八.数组指针与指针数组

        数组指针

                本质是指针,指针存储数组的内存地址(指针指向数组)

int arr[5] = {1,2,3,4,5};
int (*parr)[5] = &arr;    //数组指针  parr 和 &arr

int brr[3][7] = {};
int (*pbrr)[7] = brr;                     //数组名即首元素内存地址   &brr[0]   数组指针

int (*pcrr)[3][7] = &brr;   //对二维数组取地址   数组指针    二维数组指针

        指针数组

                本质是数组,数组中元素的类型是指针

int a,b,c,d,e;
int *arr[5] = {&a,&b,&c,&d,&e};

九.函数指针和指针函数

        函数指针

                本质是指针,即指针指向函数

void func(void){

}

void (*pf)(void) = func;   // &func;  *func;   pf就是函数指针
//pf指向的函数 返回值类型为void  且参数列表也为void
pf();

int bar(int a,int arr[],int n){}

int (*pb)(int,int *,int) = bar;
int arr[5] = {};
pb(10,arr,5);    //函数指针赋值之后  可以 当作函数名一样使用
//函数指针即存储函数的内存地址  当函数指针指向函数时,函数指针可以当作函数一样使用

        指针函数

                本质是函数,即函数返回指针类型

int *func(void){}
void *malloc(size_t size);

十.const与指针

const char *s1;      //const修饰 *s1  *s1只读    s1可以修改
     --常量指针       指针指向常量
char const *s2;      //const修饰 *s2

char * const s3;     //const修饰 s3  s3只读    *s3可以修改
	--指针常量   即指针是一个常量 
const char * const s4; //第一个修饰 *s4  第二个const修饰 s4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值