C语言指针详解

*系统为每一个字节提供一个32位地址编号 0x0000 0000–0xFFFF FFFF,四个字节
*数据存放在存储器的内存单元中,不同数据类型的数据占用的内存单元不相同
*通过内存单元的地址可以准确找到该内存单元,这个内存单元的地址也叫做指针,指针就是内存地址
*内存单元指针:银行卡号,内存单元内容:银行卡信息,余额等
*指针变量:用一个变量来存放指针,一个指针变量的值就是某个内存单元的地址或者说是内存单元的指针
*访问数据的方式:直接访问,通过变量访问,间接访问,通过指针访问地址达到访问内存中数据的目的

指针变量的初始化:

指针变量在操作之前必须指向合法的地址空间

int num=10;
int *p;
p=#   

这里是指向了num的地址,具有合法的地址空间
指针变量如果不初始化,立即操作,会出现端错误
指针变量如果没有指向合法的空间,建议指向NULL int*p=null;null的本质,地址编号是0
将指针变量初始化为合法地址(变量的地址,动态申请的地址,函数路口地址)

int data=10,p=&data;

定义了一个int的变量data和int类型的指针,把data的地址赋值给p,不是赋值给*p,*只是修饰指针P,表明这是一个指针,*p代表指针指向的内容

指针变量只能存放指针地址,不能将一个非零数或者其他任何非地址类型的数据赋值给一个指针变量

int *p=2 //错误赋值
int *p=0;//正确赋值,表示指针执行空

初始化的两种方法
1:指针声明的同时给指针赋值 char i=11; char *p = &i;
2:不在指针定义的时候初始话 char i=11; char *p; p=&i;

指针变量的类型:

1:指针变量自身类型:int *p:的指针类型是int *
2:指针变量指向的类型:int *p 的指向类型是 int

指针变量的指向类型决定了取值宽度
指针变量的指向类型决定了加一个存储单元

int main()
{
    int *p1=NULL;
  printf("P1=%p\n",p1);  //00000000
  printf("P1+1=%p\n",p1+1);//00000004

    short *p2=NULL;
  printf("P2=%p\n",p2);//00000000
  printf("P2+1=%p\n",p2+1);//00000002

    char *p3=NULL;
  printf("P3=%p\n",p3);//00000000
  printf("P3+1=%p\n",p3+1);//00000001
}
int num=0x01020304;
int *p=#    // *p=0x01020304
short *p2=#	 //*p2=0x0304
char *p3=# // *p3=0x4
int main()
{
   int num=0x01020304;
   char *p1=(char*)#  
   printf("%#x\n",*(short*)(p1+1));  
}

//指针类型是char *,指针所指向的数据类型是char,*p1=&num是取出num的值0x01020304,
//给定一个(char*)&num就是取出num的值为char类型也就是取出一个字节
//(short*)(p1+1);p1+1是char类型,也就是跳过一个字节,开始取值,取short(两个字节的长度)的值

指针变量的加减运算只能对数组指针变量进行,对指向其他类型变量的指针变量做加减运算是毫无意义的

int  a[5],*pa;
pa=a;
pa=pa+2;//pa指向a[2],即p[a]的值为&pa[2],

指针变量的注意事项:

1:void不能定义指针变量,不能给变量开辟字节
2:void*可以定义指针变量:void *p;p自身类型为void *

int num=10;
void *p=#

万能指针void * 可以保存任意一级指针的地址编号
不能直接对void p的指针取

int num =10;
void *p=#
*p;//错误,p的指向类型为void,无法确定p的宽度,取*必须要知道它的宽度,取*之前要对其进行强制转换

void指针可以接受其他数据类型指针的值,但是如果需要将void指针的值赋值给其他类型的指针需要强制类型转换
不能对void指针进行算数运算,声明void指针p后,p++,p–都不合法

指针与数组

#define SIZE  4
int main(void)
{
    short datas[SIZE];
    short *ptr;
    short index;
    double bills[SIZE];
    double *ptf;
    ptr = datas;
    ptf = bills;
    printf("%23s %10s\n","short","double");
    for(index = 0;index < SIZE; index++)
    {
        printf("pointer + %d:%10p %10p\n",index,ptr+index ,ptf+index);
    }
    return 0;
}

输出

                  short     double
pointer + 0:  0060FEEC   0060FEC8
pointer + 1:  0060FEEE   0060FED0
pointer + 2:  0060FEF0   0060FED8
pointer + 3:  0060FEF2   0060FEE0

指针取数组的首地址,数组的首地址也就是数组第一个元素的地址,对指针加一的结果是对该指针增加一个存储单元,所以指针必须声明它所指向的对象的数据类型,上述程序中,short类型的数组data,每个元素占用2个字节,所以指向该数组的指针ptr每次加1,就是在原地址的基础上加一个存储单元,也就是两个字节。

datas + 2 == &datas[2];    //相同地址
*(datas + 2 ) == datas[2];   //相同值
*datas + 2 ==datas[0] + 2;

指针的操作:

int url[5]={1,2,3,4,5};
int *ptr1,*ptr2,*ptr3

1:赋值
ptr1 = url;
ptr2 = &url[2];
2:求值
*ptr1
3:取指针地址
&ptr1
4:将一个整数加给指针
*(ptr+4) = url[4]
5:增加指针的值
ptr1++ 指针的值加1,也即是指针所指向的地址加1个存储单位,这里是int类型也就是地址加4字节
6:从指针中减去一个整数
ptr2–, 同加类似,减去一个整数就是减去一个存储单元
7:求差值
ptr2 - ptr1
两个指针求差值就是计算这两个指针所指向元素的距离,差值的单位对应相应数据类型的大小
8:比较
比较两个指针的值,前提是两个指针具有相同的类型

指针与函数的关系

指针变量作为函数的参数
如果想在函数内部修改外部变量的值,需要将外部变量的地址传递给函数
单向传递之传递地址,函数内部可以修改外部变量的值
将实参的地址传递进函数中函数中,通过地址直接操作原变量的值

void set_data(int *p)
{
    *p=100;//*p=num;
}
void test ()
{
    int num=0;
    set_data(&num);//p=&num
    printf("num=%d",num);  //100
}
int main()
{
   test(); 
}

资料参考C语言中取地址符&做函数形参?

函数指针和指针函数

函数指针就是一个指针,这个指针指向函数

int (*f)(int a, int b); // 声明函数指针

指针函数是一个函数,返回值为指针

  int *f(int a, int b);//返回值是一个int类型的指针,是一个地址

函数指针的声明
声明一个指向特定函数类型的指针,首先声明一个该类型的函数,然后用(*pt)形式的表达式来替代函数名称,pt就成为可指向那种类型函数的指针了

void ToUpper(char *) //该函数的类型是具有char* 类型的参量,返回值是void的函数
void (*pt) (char *)   //pt是一个指向函数的指针,(*pt)是一个函数
void  *pt  (char *)  // pt是一个返回指针的函数
pt = ToUpper;    //合法 ToUpper是ToUpper函数的首地址
int round (double);
pt = round ; //不合法,round和pt的类型不同

可以通过函数指针来访问函数

char mis[] = " AAA ";
(*pt)(mis);   通过*pt访问ToUpper函数

函数指针和数据指针一样,最普遍的用法是作为函数的参数

void show ( void (*fp)(char*),char *str) // 定义一个可以接收函数作为参数的函数指针,之后可以直接调用
{
	(*fp)(str);  //把用户选择的函数作用与str
	puts(str);  //显示结果
	
}
//fp是一个函数指针,str是一个数据指针
show (ToUpper,mis)  //fp=ToUpper
show (pf,mis)  //pf=pt

const 与指针

const 可以对数据起到保护作用,防止数据被修改
用 const 可以用来创建符号常量,类似于define const double PI = 3.14
指向常量的指针不能用于修改数值

double rates[5]={1,2,3,4,5}
const double * pd = rates; //pd被声明为const double类型的指针,不可以使用pd来修改它所指向的值

可以将pd指向其他地址,例如 pd++;让pd指向rate[1],合法

指针赋值和const的规则
将常量或者非常量数据的地址赋值给指向常量的指针是合法的
只有非常量的数据地址才能赋值给普通指针,否则如果将常量地址赋值给普通指针,那么就可以通过操作指针地址来实现修改数据
注意const的位置对指针的影响
如果const在前面 例如 const double * pd = rates; pd被声明为const double类型的指针,不可以使用pd来修改它所指向的值
如果const在后面 例如 double * const pd = rates; pd被初始化为rates数组的开始处rates[0],这个指针一直指向该位置,只可以改变该位置的值,不能改变其他位置的值
使用两个const来创建指针,这个指针即不可以更改所指向的位置,也不可以更改指向的数据const double * const pd = rates;

int main(void)
{
   int  const a=10;
   const int *p; //定义指针内容无法改变
   p=&a;   //const int *p = a; p指向const int的指针,无法使用p来修改a的数值
   //a=a+1;	  //错误,a的内容无法改变
  // *p=*p+1; //错误,指针的内容已经无法改变
   printf("p的地址为%p\n",p);
   printf("a的地址为%p\n",&a);
   printf("p的值为%d\n",*p);
   printf("a的值为%d\n",a);
   /*想要修改已经被const定义了的数值,可以通过指针取地址来改变,前提是该指针不是被定义的常量,
   int  const a=10;
   int *p;
   *p=*p+1; //a=11;
   */

}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值