C语言——理解指针(一级指针和二级指针)

什么是指针?

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。

指针是个变量,存放内存单元的地址。
对应到代码:

#include <stdio.h> 
int main() {    
 int a = 10;  //在内存中开辟一块空间    
 int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。               
             //将a的地址存放在p变量中,p就是一个之指针变量。    
 return 0; 
}

总结:指针就是变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。

一个小的单元到底是多大?(1个字节)

  • 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针 变量的大小就应该是4个字节。
  • 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。

总结

  • 指针是用来存放地址的,地址是唯一标示一块地址空间的。
  • 指针的大小在32位平台是4个字节,在64位平台是8个字节。

指针和指针类型

这里我们在讨论一下:指针的类型我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢?准确的说:有的。
当有这样的代码:

int num = 10; 
p = &num;

要将&num(num的地址)保存到p中,我们知道p就是一个指针变量,那它的类型是怎样的呢? 我们给指针变量相应的类型。

char  *pc = NULL; 
int   *pi = NULL; 
short *ps = NULL; 
long  *pl = NULL; 
float *pf = NULL; 
double *pd = NULL;

这里可以看到,指针的定义方式是: type + * 。 其实: char* 类型的指针是为了存放 char 类型变量的地址。 short* 类型的指针是为了存放 short 类型变量的地址。 int* 类型的指针是为了存放 int 类型变量的地址。

那指针类型的意义是什么?
指针+整数

#include <stdio.h> 
#include <stdlib.h>
int main() {    
 int n = 10;    
 char *pc = (char*)&n;    
 int *pi = &n;        
 printf("%p\n", &n);    
 printf("%p\n", pc);    
 printf("%p\n", pc+1);    
 printf("%p\n", pi);    
 printf("%p\n", pi+1);   
 system("pause");
 return 0; 
} 

运行结果:
在这里插入图片描述
总结:指针的类型决定了指针向前或者向后走一步有多大(距离)。

指针的解引用

#include <stdio.h>
#include <stdlib.h>
int main() {
 int n = 0x11223344;    
 char *pc = (char *)&n;    
 char *pi = &n;    
 *pc = 0x55;//重点在调试的过程中观察内存的变化。    
 *pi = 0;   //重点在调试的过程中观察内存的变化。
 system("pause");
 return 0; 
}

总结: 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如:char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

一级指针总结

1.做函数参数—间接修改普通变量

void setmem(int *p)
{
 * p = 100;
}
int main()
{
 int n = 10;
 int *p = &n;
 * p = 20;//--间接修改普通变量
 setmem(p);//--间接修改普通变量
 return 0;
}

2.做输入输出

#include <stdlib.h>
#include <stdio.h>
int showList(char *str)
{
 if (str == NULL)
  return 0;
 else
  return 1;
}
int main()
{
 char *str = "hello world!";
 if (showList(str) == 0)
  printf("error!\n");
 else
  printf("%s\n", str);
 system("pause");
 return 0;
}

总的来说就是一句话:间接修改数据、传递地址。
下面是一级指针的主要用途:

  • 可以利用一级指针改变函数外部的变量,还可以跨进程改变变量(外挂就是这么搞的)。
  • 一级指针可以存储数组的首地址,并通过指针或者下标访问元素。
  • 一级指针作为函数的返回值,返回地址;注意:不能返回指向栈的地址,因为函数执行完,变量就被回收了。
  • 函数的参数有副本机制,传递实参时,新建一个变量,容纳传递过来的实参。特例:数组在函数参数中拒绝副本机制,数组作为参数时数组的首地址。
  • return也有副本机制,返回值保存在CPU寄存器中,因此函数的返回值不能取地址。
  • 为什么指针要有类型,因为类型可以让编译器知道如何解析,还有步长。

二级指针总结

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里? 这就是二级指针 。
在这里插入图片描述
对于二级指针的运算有:

  • *ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa
int b = 10; 
*ppa = &b;//等价于 pa = &b;
  • **ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a
**ppa = 30; 
//等价于*pa = 30; 
//等价于a = 30; 

指针的本质就是地址, 那么几级指针也只是一个地址, 唯一不同的就是寻址的结果(*p)

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值