转:指针知识梳理1-变量基本定义及使用

本文详细解析了C语言中指针的基本概念与使用方法,包括指针变量的定义、地址与数据的关系、指针的赋值操作、*符号的作用、指针的加减运算等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://blog.youkuaiyun.com/xiaoliu0518/article/details/32707111

一、指针变量、地址、数据、内存关系

在学习指针之前,我们先统一几个概念。

(1)在计算机中本质 用 内存 来存储 数据 ,在我们写代码的时候,用变量来存储数据 。

(2)变量是在编程语言中的概念,方便我们编程,当编译运行起来以后,就只有内存了和数据了。

  比如 当 我们写代码  

  1. int a;   
  2. int b;   
  3. a = 1;  
  4. b = a;  
第1行第2行,语法层面是 定义两个变量,计算机层面是在内存中申请 2个4字节内存,a地址 0x10,b地址  0x0c

第3行,语法层面是 给变量a赋值1,计算机层面是,把数据1写到地址为0x10-0x13的4个字节内存中。

第4行,语法层面是把a的值赋值给b ,计算机层面是,把0x10-0x13的4个字节的内存中存储的数据读出来,写到 0x0c-0x0f的4个字节的内存中。


(3)描述内存只有两个属性:地址,大小,我们可以说我们访问的是从某个地址开始 多少字节的内存。

(4)在代码中我们要得到变量的地址,其实本质是内存的地址,&a;

(5)在我的文章中,指针 是 指针变量的缩写,以后所说指真是说的  指针变量, 指针是指针变量,指针是变量。

(6)在语法层面,我们要存储数据,需要用到变量,比如 int  a = 1, 地址也是一种数据,在语法中存储 地址,需要用到 指针变量。

(7)地址这种数据 本质也是  1 2 3 4 5。。。等整数,只不过在我们的语法层面,数据有数据的类型,是地址类型。


二、指针变量基本使用

1、指针变量的定义,及赋值

在C语言中 变量定义的基本模型是

数据类型   变量名;

type  name;

我们写如下代码

  1. int a; //a 的类型是int  
  2. int *p; //p的类型是 int*  
  3. p = &a; //&a得到的数据,类型是int*,在C语言中,在赋值的时候类型要匹配。  

p是一个指针变量,它的类型是(int*)。

p是一个指针变量,他存储  地址  这种类型的数据。

&符号是用来计算变量的地址,a是int变量,int变量的地址   类型是 (int*)。

同理,char 变量的地址 类型是(char*),double 变量的地址类型是(double *);

因此可以有如下代码:

  1. char b;  
  2. char *p1;  
  3. p1 = &b;  
  4. double c;  
  5. double *p2;  
  6. p2 = &c;  

解释: p = &a;

变量p 存储了 变量a的地址,也就是所谓 p 指向a ,在我们初学指针的时候,不要说指向这个词,而是把他的概念说全(变量p 存储了 变量a的地址)。

可以看下面内存图,这里验证下 sizeof(p)看p占多少个字节。



2、* 符号作用解释

首先在定义指针变量的时候

type *p;   //这里理解 *是形容词,修饰变量p 是个指针变量,那么 *前面的type有什么作用呢?我们在下面慢慢理解。

  1. int  a,b;  
  2. int *p;  
  3. p = &a;  
  4. *p = 1;  
  5. b= *p;  
以上代码,第4行,*p 做的是:首先读取p 变量的值,这个值是变量 a的地址,然后通过读取的这个地址 找到a的内存,然后往a的内存中写1。

第5行:首先读取p 变量的值,这个值是变量 a的地址,然后通过读取的这个地址 找到a的内存,然后读取这块内存的数据并把它写入到b的内存中。

由此,我们可以理解 在定义的时候,*是个形容词,形容变量是个指针变量,在使用的时候,*是个动词,是通过地址找到内存,并读写。

初学的时候把这个过程说完整。

*前面的type决定了通过p存储的地址读写该内存的方式:要读写一块内存,需要知道内存的地址,大小,和如何把数据换算成二进制放到这块内存中。

比如

(1)----------------------------------------------------------------------------------------------------------------------

int  a ;

double b ;

a = 1;

b = 1.1;

当给a赋值的时候,我知道a 的地址,然后知道要写4个字节,还知道这四个字节的数据应该写 1转换成二进制。

当给b赋值的时候,我知道b 的地址,然后知道要写8个字节,还知道这八个字节的数据应该写 1.1按照一定的规则转换成的二进制。

(2)----------------------------------------------------------------------------------------------------------------------

int *p1 ;

char *p2;

假定 p1 p2 的值都是 0x10,也就是p1 p2存储的地址都为 0x10;

*p1 = 1的时候通过p1存储的地址访问0x10 0x11 0x12 0x13 这4个字节,并在这4个字节中了一个(int )1,也就是 二进制  00000000 00000000 00000000 00000001。

*p2 = 1的时候通过p2存储的地址访问0x10这一个字节,并在这一个字节中写了一个(char)1,也就是00000001。

注意以下代码:

  1. int  a;  
  2. int *p = &a;  
  3. *p = 1;  
第二行是 p 变量的初始化,是在访问p本身的内存

第三行是通过p存储的地址找到一块内存,是在访问a的内存,也就是所谓p指向的内存。


在做*p的时候,一定要注意p 要存储一个合法有效的地址,否则就会访问一块未知内存,出现段错误,这是前期经常犯的错误。

目前要得到一个合法有效的地址 就是对 变量取地址,&a,以后还会接触到malloc.


完整测试代码如下:

  1. #include <stdio.h>  
  2. int main()  
  3. {  
  4.     int a = 0;  
  5.     int *p = &a;  
  6.     //打印地址用 %p,会以16进制打印。  
  7.     printf("p  = %p",p);  
  8.     printf("&a = %p",&a);     
  9.       
  10.     *p = 1;  
  11.     printf("a = %d\n",a);  
  12.     printf("*p = %d\n",*p);  
  13.       
  14.     return 0;  
  15. }  

  1. #include <stdio.h>  
  2. //验证指针变量的size  
  3. int main()  
  4. {  
  5.     char a;  
  6.     int b;  
  7.     double c;  
  8.     char *p1;  
  9.     int *p2;  
  10.     double *p3;  
  11.     printf("%d\n",sizeof(a));  
  12.     printf("%d\n",sizeof(b));  
  13.     printf("%d\n",sizeof(c));  
  14.     printf("%d\n",sizeof(*p1));  
  15.     printf("%d\n",sizeof(*p2));  
  16.     printf("%d\n",sizeof(*p3));  
  17.     return 0;  
  18. }  

3、指针加减法

根据如下代码验证:

指针变量 加上 数字,计算的是位移,跟我们常规的数学计算略有不同。

type  *p;

 p 存储地址 addr

p+n  计算出来的值 为 addr+n*sizeof(type);

比如:

int  *p1;

char *p2;

如果 p1 = 0,p2 = 0;

则 p1+1 计算出的值为 4;

p2+1 计算出的值为 1;

对于 type *p ;来说 ,type决定了指针加减法偏移位移的多少。

以下代码验证。


  1. #include <stdio.h>  
  2. int main()  
  3. {  
  4.     /* 
  5.     指针变量的加减 
  6.     1、type *p;  
  7.     2、指针变量+/-一个数字 计算的是位移 
  8.        p  = addr; 
  9.        p+n  =  addr+n*sizeof(type); 
  10.      
  11.     */  
  12.     int a = 1;  
  13.     int *pa = &a;  
  14.       
  15.     char c = 0;  
  16.     char *pc = &c;  
  17.       
  18.     printf("pa = %p\n",pa);  
  19.     p++;  
  20.     printf("pa = %p\n",pa);  
  21.     p+=5;  
  22.     printf("pa = %p\n",pa);   
  23.       
  24.       
  25.     printf("pc = %p\n",pc);  
  26.     pc++;  
  27.     printf("pc = %p\n",pc);  
  28.     pc+=5;  
  29.     printf("pc = %p\n",pc);   
  30.       
  31. }  
我们画 pa 和 a的内存图.




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值