首页 > 代码库 > 指针知识梳理1-变量基本定义及使用
指针知识梳理1-变量基本定义及使用
一、指针变量、地址、数据、内存关系
在学习指针之前,我们先统一几个概念。
(1)在计算机中本质 用 内存 来存储 数据 ,在我们写代码的时候,用变量来存储数据 。
(2)变量是在编程语言中的概念,方便我们编程,当编译运行起来以后,就只有内存了和数据了。
比如 当 我们写代码
int a; int b; a = 1; 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;
我们写如下代码
int a; //a 的类型是int int *p; //p的类型是 int* p = &a; //&a得到的数据,类型是int*,在C语言中,在赋值的时候类型要匹配。
p是一个指针变量,它的类型是(int*)。
p是一个指针变量,他存储 地址 这种类型的数据。
&符号是用来计算变量的地址,a是int变量,int变量的地址 类型是 (int*)。
同理,char 变量的地址 类型是(char*),double 变量的地址类型是(double *);
因此可以有如下代码:
char b; char *p1; p1 = &b; double c; double *p2; p2 = &c;
解释: p = &a;
变量p 存储了 变量a的地址,也就是所谓 p 指向a ,在我们初学指针的时候,不要说指向这个词,而是把他的概念说全(变量p 存储了 变量a的地址)。
可以看下面内存图,这里验证下 sizeof(p)看p占多少个字节。
2、* 符号作用解释
首先在定义指针变量的时候
type *p; //这里理解 *是形容词,修饰变量p 是个指针变量,那么 *前面的type有什么作用呢?我们在下面慢慢理解。
int a,b; int *p; p = &a; *p = 1; 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。
注意以下代码:
int a; int *p = &a; *p = 1;第二行是 p 变量的初始化,是在访问p本身的内存
第三行是通过p存储的地址找到一块内存,是在访问a的内存,也就是所谓p指向的内存。
在做*p的时候,一定要注意p 要存储一个合法有效的地址,否则就会访问一块未知内存,出现段错误,这是前期经常犯的错误。
目前要得到一个合法有效的地址 就是对 变量取地址,&a,以后还会接触到malloc.
完整测试代码如下:
#include <stdio.h> int main() { int a = 0; int *p = &a; //打印地址用 %p,会以16进制打印。 printf("p = %p",p); printf("&a = %p",&a); *p = 1; printf("a = %d\n",a); printf("*p = %d\n",*p); return 0; }
#include <stdio.h> //验证指针变量的size int main() { char a; int b; double c; char *p1; int *p2; double *p3; printf("%d\n",sizeof(a)); printf("%d\n",sizeof(b)); printf("%d\n",sizeof(c)); printf("%d\n",sizeof(*p1)); printf("%d\n",sizeof(*p2)); printf("%d\n",sizeof(*p3)); return 0; }
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决定了指针加减法偏移位移的多少。
以下代码验证。
#include <stdio.h> int main() { /* 指针变量的加减 1、type *p; 2、指针变量+/-一个数字 计算的是位移 p = addr; p+n = addr+n*sizeof(type); */ int a = 1; int *pa = &a; char c = 0; char *pc = &c; printf("pa = %p\n",pa); p++; printf("pa = %p\n",pa); p+=5; printf("pa = %p\n",pa); printf("pc = %p\n",pc); pc++; printf("pc = %p\n",pc); pc+=5; printf("pc = %p\n",pc); }我们画 pa 和 a的内存图.