初阶第六节-指针

1.指针是什么

#include <stdio.h>
int main()
{
	int a = 10;//a是整型变量,占用4个字节的变量,在内存中开辟一块空间

	int* pa = &a;//这里我们对变量a,取出它的地址,可以使用&操作符
	            //a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在pa变量中
	            //pa就是一个指针变量,用来存放地址的
	
	//本质上指针就是地址;
	//口语说的指针,其实是指针变量,指针变量就是一个变量,指针变量是用来存放地址的一个变量
	return 0;
}

2.指针和指针类型 

2.1指针+-整数 

#include<stdio.h>
int main()
{
	int n = 10;

	int* pa = &n;
	char* pc = (char*)&n;

	printf("%p\n", &n);
	printf("%p\n", pa);
	printf("%p\n", pa + 1);

	printf("%p\n", pc);
	printf("%p\n", pc + 1);

	//结论:
	// 指针的类型决定了指针+-1操作的时候,跳过了几个字节
	//决定了指针的步长
	
	//100 - 10进制
	//0X64 - 16进制
	//1100100 - 二进制
	//144 - 8进制
	
	return 0;
}

2.2指针的解引用 

//X86 - 32位的环境 - 4 
//X64 - 64位的环境 - 8

#include<stdio.h>
int main()
{
	char* pc = NULL;
	int* pi = NULL;
	short* ps = NULL;
	long* pl = NULL;
	float* pf = NULL;
	double* pd = NULL;

	//sizeof 的返回值是无符号的整型 - unsigned int
	printf("%zu\n", sizeof(pc));//4
	printf("%zu\n", sizeof(pi));//4
	printf("%zu\n", sizeof(ps));//4
	printf("%zu\n", sizeof(pl));//4
	printf("%zu\n", sizeof(pf));//4
	printf("%zu\n", sizeof(pd));//4

	return 0;
}


#include<stdio.h>
int main()
{
	int a = 0X11223344;
	int* pa = &a;
	*pa = 0;
	printf("%x\n", a);//00000000

	char* pc = (char*)&a;
	*pc = 0;
	printf("%x\n", a);//11223300

	//结论:
	//指针类型决定了指针在被解引用的时候访问了几个字节
	//如果是int*的指针,解引用访问4个字节
	//如果是char*的指针,解引用访问1个字节
	//推广到其它类型
	
	return 0;
}
#include<stdio.h>
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. 野指针

概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

3.1 野指针成因 

//1. 指针未初始化
#include<stdio.h>
int main()
{
	int* p;//p没有初始化,就意味着没有明确的指向
	//p是一个局部的指针变量,局部变量不初始化的话,默认是随机值:0Xcccccccc

	*p = 20;//非法访问内存了,这里的p就是一个野指针
	return 0;
}
//2.越界访问
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = arr;//int* p = &arr[0]
	int i = 0;
	for (i = 0; i <= 10; i++)//当指针指向的范围超出数组arr的范围时,p就是野指针
	{
		*p = i;
		p++;
	}
	return 0;
}

 

3. 指针指向的空间释放

#include<stdio.h>
int* test()
{
	int a = 10;//在局部变量开辟了一块空间,出了函数后就会返还空间给操作系统
	return &a;
}
int main()
{
	int*p = test();
	printf("hehe\n");
    
	printf("%d\n", *p);//随机值
	return 0;
}

3.2 如何规避野指针 

4. 指针运算 

 4.1 指针+-整数

#include<stdio.h>
#define N_VALUES 5
int main()
{
	float values[N_VALUES];
	float* vp;
	//指针+-整数;指针的关系运算
	for (vp = &values[0]; vp < &values[N_VALUES];)
	{
		*vp++ = 0;
	}
	return 0;
}

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	//代码1
	//for (i = 0; i < sz; i++)
	//{
	//	arr[i] = 1;
	//	printf("%d ", *p);
	//}

	//代码2
	//int* p = arr;
	//for (i = 0; i < sz; i++)
	//{
	//	*p = 1;
	//	printf("%d ", *p);
	//	p++;
	//}

	//代码3
	//int* p = arr;
	//for (i = 0; i < sz; i++)
	//{
	//	*(p + i) = 1;
	//	printf("%d ", *p);
	//}

	//代码4
	//int* p = arr;
	//int* pend = arr + 9;
	//while (p<=pend)
	//{
	//	*p = 1;
	//	printf("%d ", *p);
	//	p++;
	//}

	return 0;
}

4.2 指针-指针

#inlcude<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	char c[5];
	//指针和指针相减的前提:
	//两个指针指向同一块空间
	printf("%d\n", &arr[9] - &c[0]);//err

	// |指针-指针|的绝对值是指针和指针之间的元素个数
	printf("%d\n", &arr[9] - &arr[0]);//9
	return 0;
}

#include<stdio.h>
int my_strlen(char* str)
{
	char* start = str;
	while (*str != '\0')
	{
		str++;
	}
	return str - start;
}
int main()
{
	int len = my_strlen("abc");//求字符串长度
	printf("%d\n", len);//3
	return 0;
}

 4.3 指针的关系运算

5. 指针和数组

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10};

	int* p = arr;//数组名
	printf("%d\n", arr[2]);
	printf("%d\n", p[2]);//p[2] --> *(p+2)

	//[] 是一个操作符  2和arr是两个操作数
	printf("%d\n", 2[arr]);
	printf("%d\n", arr[2]);

	//arr[2] --> *(arr+2)-->*(2+arr)-->2[arr]

	//arr[2] <==> *(arr+2) <==> *(p+2) <==> *(2+p) <==> *(2+arr) == 2[arr]
	//2[arr] <==> *(2+arr)
	return 0;
}
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = arr;//等价于int* p = &arr[0]

	printf("%p\n", arr);//数组名arr是数组首元素的地址
	printf("%p\n", &arr[0]);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%p <==> %p\n", &arr[i], p + i);//地址相同
	}

	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}

#include<stdio.h>

//代码1
//void test(int* p, int sz)
//{
	//int i = 0;
	//for (i = 0; i < sz; i++)
	//{
		//printf("%d ", *(p + i));
	//}
//}

//代码2
void test(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);//arr[i]->*(arr+i)
	}
}

int main()
{
	int arr[10] = { 0 };
	test(arr, 10);
	return 0;
}

6. 二级指针 

#include<stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;//pa是一个指针变量,一级指针变量

	//ppa就是一个二级指针变量
	int ** ppa = &pa;//ppa也是个变量,&pa取出pa在内存中起始地址

	//*pa = 20;
	**ppa = 20;//*ppa通过对ppa中的地址进行解引用,这样找到的是pa,*ppa其实访问的就是pa
               //**ppa先通过*ppa找到pa,然后对pa进行解引用操作:*pa,然后找到a

	printf("%d\n", a);

	int*** pppa = &ppa;
	return 0;
}

 7. 指针数组

//指针数组 - 数组
//存放指针的数组就是指针数组

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int* pa = &a;
	int* pb = &b;
	int* pc = &c;

	int arr[10];//整型数组 - 存放整型的数组就是整形数组
	char ch[5];//字符数组 - 存放的是字符
	
	int* parr[10] = {&a, &b, &c};//parr就是整形指针的数组 - 存放整型指针的数组
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%d ", *(parr[i]));//10 20 30
	}
	return 0;
}

#include<stdio.h>
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]);
		}
		printf("\n");
	}
	return 0;
}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值