指针(简单版)

49 阅读4分钟

指针

1.指针是什么

指针是内存中一个最小单元的编号,也就是地址

指针变量是用来存放内存地址的变量

本质上指针就是地址

指针变量大小是4个字节

type+*

#include<stdio.h>
int main()
{

	int a = 10;
	int* p = &a;
	return 0;
}

2.指针和指针类型

(1)指针+整数

指针类型决定了指针在被解引用的时候访问几个字节

int* 4个字节

char* 1个字节

#include<stdio.h>
int main()
{

	char* pc = NULL;
	short* ps = NULL;
	int* pi = NULL;
	double* pd = NULL;
	//sizeof 返回的值的类型是无符号整型  unsigned int
	printf("%zu\n", sizeof(pc));
	printf("%zu\n", sizeof(ps));
	printf("%zu\n", sizeof(pi));
	printf("%zu\n", sizeof(pd));
	return 0;
}

指针字节数.png

int main()
{
	int a = 0x11223344;
	int* pa = &a;
	char* pc = (char*)&a;
	printf("pa=%p\n", pa);
	printf("pa+1=%p\n",pa + 1);

	printf("pc=%p\n", pc);
	printf("pc+1=%p\n", pc + 1);
	return 0;
}

指针类型解引用.png

指针的类型决定了指针+1 -1操作的时候,跳过几个字节

(决定了指针的步长)

指针变量解引用直观图.png

(2)指针的解引用

int main()
{
    int a = 0;
    int* pi=&a;//pi 访问4个字节,pi+1也是跳过4个字节
    float* pf=&a;//pf解引用访问4个字节,pf+1也是跳过4个字节
    //int* 和float*不能通用
    //*pi = 100;
    //*pf = 100.0;
    return 0;
    
}

3.野指针

(1)野指针就是指针指向的位置是不可知的

int main()
{
	int* p;
	//p没有初始化,就意味着没有明确的指向
	//一个局部变量不初始化的化,放的是随机值
	*p = 10;//非法访问内存,这里的p就是野指针
	return 0;
}

(2)指针越界访问

int main()
{
	int arr[10] = { 0 };
	int* p = arr;//&arr[0]
	int i = 0;
	for (i = 0;i <= 10;i++)
	{
		*p = i;
		p++;//当指针指向的范围超出数组arr的范围时,p就是野指针
	}
	return 0;
}

(3)指针指向的空间释放

int* test()
{
	int a = 10;
	return &a;
}
int main()
{
	int* p = test();
	return 0;
}
//空间已经不属于该程序,但是还存在于内存之中

(4)避免野指针的方法

1.指针初始化

2.小心指针越界

3.指针指向空间释放即时置NULL

4.避免返回局部变量的地址

5.指针使用之前检查有效性

int main()
{
	//int b = 0;
	//int a = 10;
	//int* p = &a;
	//*p = 20;
	//NULL->0

	//int* p2 = NULL;
	//*p2 = 100;//err

	int* p3 = NULL;

	if (p3 != NULL)
	{
		*p3 = 100;//ok
	}

	return 0;
}

4.指针运算

指针+-整数

指针-指针

指针的关系运算

4.1指针+-整数

#define N_VALUES 5
float values[N_VALUES];
float* vp;
//指针的关系运算
for (vp = &values[0];vp < &values[N_VALUES];)
{
	*vp++ = 0;//*vp->vp++    注意与(*vp)++的区别
}

vp的直观图·.png

4.2指针-指针

int main()
{
	int arr[10] = { 0 };
	printf("%d\n", &arr[9] - &arr[0]);

	return 0;

}

指针-指针.png

指针-指针得到的绝对值是指针和指针之间的元素个数

指针-指针的直观图.png

不是所有的指针都能相减

指向同一块空间的2个指针才能相减

int main()
{
	//int arr[10] = { 0 };
	//printf("%d\n", &arr[9] - &arr[0]);
	int arr[10] = { 0 };
	char ch[5] = { 0 };
	printf("%d\n", &ch[0] - &arr[5]);//err

	return 0;

}

指针-指针求字符串长度

int my_strlen(char* str)
{
	char* start = str;
	while(*str !='\0')
	{
		str++;
	}
	return (str - start);
		


}

int main()
{
	int len = my_strlen("abcdef");
	printf("%d\n", len);

	return 0;
}

指针-指针求字符串长度.png

4.3指针的关系运算

#define N_VALUES 5
float values[N_VALUES];
float* vp;

for (vp =  &values[N_VALUES];vp >= &values[0];)
{
	*--vp = 0;
}

第一种写法直观图.png

第二种(不建议)

#define N_VALUES 5
float values[N_VALUES];
float* vp;

for (vp = &values[N_VALUES-1] ;vp >= &values[0];vp--)
{
	*vp = 0;
}

指针第二种方法(倒着写).png

倒着写直观图.png

5.指针和数组

int main()
{
	int arr[10] = { 0 };
	//arr是首元素的地址
	//&arr[0]
	int* p = arr;
	//通过指针来访问数组
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0;i < sz;i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}

指针和数组的结果.png

int main()
{
	int arr[10] = { 0 };
	//arr是首元素的地址
	//&arr[0]
	int* p = arr;
	//通过指针来访问数组
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0;i < sz;i++)
	{
		printf("%p-------%p\n", &arr[i], p + i);
        //printf("%d ",arr[i]);
        //printf("%d ",*(p+i));
        //printf("%d ",*(arr+i));
        //arr[i]-->*(arr+i)
	}
	/*for (i = 0;i < sz;i++)
	{
		printf("%d ", *(p + i));
	}*/
	return 0;
}

数组和指针的结果2.png

指针和数组直观图.png

6.二级指针

#include<stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;//pa是一级指针变量
	int** ppa=&pa;//ppa是一个二级指针变量
	**ppa = 20;
	//**pa = 20;
	printf("%d\n", a);
		
	return 0;
}

ppa pa 直观图.png

二级指针的结果.png

二级指针变量的直观图.png

二级指针变量是用来存放一级指针变量的地址的

7.指针数组

存放指针的数组

int main()
{
	int a = 10;
	int b = 20;
	int c = 30;

	int arr[10];

	int* pa = &a;
	int* pb = &b;
	int* pc = &c;

	//parr就是存放指针的数组
	//指针数组
	int* parr[10] = { &a,&b,&c };
    	
	int i = 0;
	for (i = 0;i < 3;i++)
	{
		printf("%d ", *(parr[i]));
	}
	return 0;
}

parr结果.png

parr直观图.png

int main()
{
int arr1[4] = { 1,2,3,4 };
int arr2[4] = { 2,3,4,5 };
int arr3[4] = { 3,4,5,6 };
int* parr[3] = { arr1,arr2,arr3 };
int i = 0;
for (i = 0;i < 3;i++)
{
	int j = 0;
	for (j = 0;j < 4;j++)
	{
		printf("%d ", parr[i][j]);//arr[i]-->*(arr+1)
	}
	printf("/n");
}
	return 0;
}

指针数组结果.png