首页 > 代码库 > 指针知识梳理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的内存图.