当前位置: 首页 > article >正文

6.指针学习

指针

  • 指针
  • 指针类型
  • 野指针
  • 指针运算
    • 指针+- 整数
    • 指针-指针
    • 指针的关系运算
  • 指针和数组
  • 二级指针
  • 指针数组

指针

  1. 指针 == 内存编号 == 地址
  2. 口语指针:指针变量,是用来存放内存地址的变量

指针变量:存放地址的变量。

  1. &取出变量的内存真实地址
  2. 把地址存放到一个变量中
  3. 这个变量就是指针变量
int main()  
{  
int a = 10;//在内存中开辟一块空间  
int* p = &a;//取a地址,p就是一个指针变量。
return 0;  
}
a变量占用4个字节的空间
将a的4个字节的第一个字节的地址存放在p变量中
p就是一个指针变量。
int* p
*:p是指针,*p是指针变量-->a
int:a是int类型

32位地址,指针变量大小是4个字节。
64位地址,指针变量大小是8个字节。

指针类型

存数据再内存中是倒着存的,访问是正着访问的

指针类型指针解引用时可访问的字节数
char*1byte
short*2byte
int*4byte

野指针

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

野指针成因

  1. 指针未初始化(随机找了一块空间)
  2. 指针越界访问(数组越界)
  3. 指针指向的空间释放了(局部变量,进函数创建,出函数销毁)
    如何规避野指针
  4. 指针初始化 int* ptr = NULL; -->空指针,没有指向有效空间,不能直接使用。
  5. 小心指针越界
  6. 指针指向空间释放,及时置NULL
  7. 避免返回局部变量的地址
  8. 指针使用之前检查有效性 if(ptr != NULL)

指针运算

指针± 整数

int main()
{
	int arr[10] = {0};
	int* p = &arr[0];
	int i = 0;
	for(i = 0;i < 10;i++)
	{
		*p = i;//将i赋值给 *p,即arr[i] = i
		p++;//给地址++
		//or
		*(p + i) = i;//在p 的基础上增加
	}
	return 0;
}
arr数组名 == 首元素地址 arr[0] == 指针 p
*(p + i)== *(arr + i) == arr[i] == i[arr] == *(i + arr)

指针-指针

地址 - 地址,前提:指向同一块空间
(指针 - 指针) 的绝对值 得到的是 指针之间的元素个数

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

}

计算字符串长度

int my_strlen(char* s)
{
	char* start = s;
	while(*s)//a b c d e f /0
	{
		s++;
	}
	return s - start;
}
int main()
{
	char arr[] = "abcdef";//a b c d e f /0
	int len = my_strlen(arr);
	printf("%d", len);
	return 0;
}

指针的关系运算

#define N_VALUES 5  
float values[N_VALUES];  
float *vp;
for(vp = &values[N_VALUES]; vp > &values[0];)  
{  
	*--vp = 0;  
}
代码简化, 这将代码修改如下
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)  
{  
	*vp = 0;  
}
实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证  
它可行。

标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较
但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

指针和数组

#include <stdio.h>  
int main()  
{  
	int arr[10] = {1,2,3,4,5,6,7,8,9,0};  
	printf("%p\n", arr);      //012FFB90
	printf("%p\n", &arr[0]);  //012FFB90
	return 0;  
}

数组名 == 数组首元素的地址 == 指针
数组是连续存放的,是一块连续的空间
可以通过 指针 访问 数组,通过 指针 遍历
&arr 的类型是 int (*)[10],而 arr 的类型是 int *

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int* p = arr;/p存放的是数组首元素的地址
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%p==%p\n", &arr[i], p + i);//010FFDFC==010FFDFC ……
		printf("%d ", *(p + i));//1 2 3 4 5 6 7 8 9 0
	}
	return 0;
}

二级指针

int main()
{
	int a = 10;
	int* p = &a;//*:p是指针,int:a是int类型
	int** pp = &p;//*:pp是指针,int*:p是int*类型
	printf("%d ", *(*pp));//10
	*(*pp) = 100;//*pp-->p;*(*pp)==*p-->a
	printf("%d ", a);//100
	return 0;
}

指针数组

存放指针(地址)的数组
eg:

int arr1[10];//存整形的数组
char arr2[10];//存字符的数组
int* arr3[10];//存整形指针的数组
int main()
{
	char arr1[] = "abcdefghijklmn";
	char arr2[] = "1,2,3,4,5,6,7,8,9,0";
	char arr3[] = "hello world";
	char* parr[] = { arr1,arr2,arr3 };//类型是char*
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%s\n", parr[i]);//%s打印只需要知道字符串起始位置,打印到\0
	}
	return 0;
}

指针数组模拟出2维数组

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int* parr[] = { arr1,arr2,arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", parr[i][j]);
			printf("%d ", *(parr[i]+j));//与上等价
		}
		printf("\n");
	}
	return 0;
}

2维数组:在内存中是连续的
指针数组:arr1,arr2,arr3不一定连续


http://www.kler.cn/a/567031.html

相关文章:

  • Linux操作系统:基于 Linux 的智能家居系统开发与实现 —— 以 FS - MP1A 嵌入式开发板为例
  • Java多线程与高并发专题——从AQS到ReentrantLock
  • 2025 蓝桥杯 Python 组部分题目解析
  • ffmpeg常用方法(一)
  • 【后端】Docker一本通
  • AI 驱动的智慧大脑:打造企业动态知识库,开启高效管理新时代
  • Vue核心知识:动态路由实现完整方案
  • 单细胞分析(19)—— 单细胞转录组基因集评分方法
  • 代码随想录算法训练营day49(0217)
  • MathJax v2版本中网络慢导致出现 Math Processing Error 问题处理
  • 哔哩哔哩IT私塾python爬虫视频教程中的项目文件
  • 【Maui】系统找不到指定的文件Xamarin.Android.Aapt2.targets
  • Python的那些事第三十六篇:基于 Vega 和 Vega-Lite 的数据可视化解决方案,Altair 声明式可视化库
  • 全国普通高等学校名单
  • Linux与UDP应用1:翻译软件
  • Spring Boot 3.x 基于 Redis 实现邮箱验证码认证
  • 华为hcia——Datacom实验指南——STP工作基本原理及STP/RSTP基本功能配置
  • PHP对接微信支付v3版本
  • 从0开始的IMX6ULL学习篇——裸机篇之外设资源分析
  • mysql系列10—mysql锁