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

指针的介绍1后

5.指针运算

5.1指针+-整数

通过指针加减整数跳过相应的字节就可以访问相应的数组元素等

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);

	int* p = &arr[0];
	for (int i = 0; i < sz; ++i)
	{
		printf("%d ", *p);
		p++;
	}
	printf("\n");
	int *q = &arr[0] + sz - 1;
	for (int i = 0; i < sz; ++i)
	{
		printf("%d ", *q);
		q--;
	}

	return 0;
}

 5.2指针-指针

指针-指针的绝对值等于指针与指针之间的元素个数

要求这两个指针指向同一块内存区域

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", &arr[0] - &arr[sz - 1]);
	printf("%d\n", &arr[sz - 1] - &arr[0]);
	return 0;
}

 数组一个九个元素,第九个元素的起始地址与第一个元素的起始地址之间正好8的元素

5.3指针之间的关系运算

即比大小

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = &arr[0];
	while (p <= &arr[sz - 1])
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}

6.野指针

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

(2)不可知的位置包括但不限于随机的、不明确的、没有明确限制的位置

6.1野指针成因

1.指针未初始化

指针未初始化,该指针指向的内容就是随机的、不明确的

2.指针越界访问

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
	int arr[] = { 1,2,3 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = &arr[0];

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

指针越界访问,得到了一个随机值

指向随机值时的指针就是一个野指针

指向1、 2、3时的指针不是野指针

3.指针指向的空间已经被释放

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int* X()
{
	int a;
	return &a;
}
int main()
{
	int* p = X();
	return 0;
}

函数调用完毕后,之前所申请的内存空间就会归还给操作系统

相应的局部变量就会被销毁不存在了

X()函数返回了一个局部变量的地址赋值给p,此时p就是一个野指针

如果再使用p去访问已经被归还的内存,就形成了非法访问

此时造成的后果包括但不限于

未定义行为、内存安全问题、程序不稳定等

6.2规避野指针

6.2.1指针初始化

int * p = NULL;

在C语言中,NULL是一个宏定义,它代表一个空指针常量

NULL用于初始化指针变量,表示该指针不指向任何有效的内存地址。这有助于防止指针在未经初始化的情况下被使用,从而避免未定义行为(如访问无效内存)。

 在C标准中,NULL通常被定义为((void*)0),但也可能简单地定义为0。这两种定义在大多数情况下是等效的,因为0被赋值给一个指针时,它会自动被转换为空指针。然而,使用((void*)0)的显式类型转换可以提供更好的类型安全性,特别是在与标准库函数交互时。

6.2.2小心指针越界

⼀个程序向内存申请了哪些空间,通过指针也就只能访问哪些空间,不能超出范围访问,超出了就是 越界访问

6.2.3指针变量不再使用时及时置为NULL,使用之前检查有效性

(1)不再使用及时置为NULL,避免非法访问,或者不必要的修改

(2)使用之前检查有效性,是为了防止未定义行为、避免内存泄漏等

7.传值传参和传址传参

7.1传值传参

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int Add(int a, int b)
{
	
	return a + b;
}
int main()
{
	int a = 1;
	int b = 2;
	int c = Add(a, b);
    printf("%d\n", c);
	return 0;
}

传入的只是a,b的值

此时,我只是希望获得a与b的和

7.2传址传参

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

void swap(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a = 1;
	int b = 2;
	printf("交换前:a = %d\n", a);
	printf("交换前:b = %d\n", b);
	swap(a, b);
	printf("交换后:a = %d\n", a);
	printf("交换后:b = %d\n", b);
	return 0;
}

 我们调用swap函数的目的是改变a与b的值

如果我们传入的是a与b的值

那么形参是实参的临时拷贝

函数调用完毕后,a与b并不会发生改变

 形参是实参的临时拷贝的解释

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

void swap(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
	printf("形参a的地址: % p\n", &a);
	printf("形参b的地址:%p\n", &b);
}
int main()
{
	int a = 1;
	int b = 2;
	printf("实参a的地址:%p\n", &a);
	printf("实参a的地址:%p\n", &b);
	swap(a, b);
	return 0;
}

 

我们发现形参与实参的地址不同

那么,既然地址不同

实际交换的就并不是main函数中实参a与b的值了

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

void swap(int *a, int *b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
int main()
{
	int a = 1;
	int b = 2;
	printf("交换前:a = %d\n", a);
	printf("交换前:b = %d\n", b);
	swap(&a, &b);
	printf("交换前:a = %d\n", a);
	printf("交换前:b = %d\n", b);
	return 0;
}

当我们传入的是a与b 的地址的时候

我么就可以在函数中通过地址找到a与b 的值

就进行常规的交换

总结:

函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值传参

函数内部要修改主调函数中的变量的值,就需要传址传参


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

相关文章:

  • [STM32 标准库]定时器输出PWM配置流程 PWM模式解析
  • 探索与创新:DeepSeek R1与Ollama在深度研究中的应用
  • 正在更新丨豆瓣电影详细数据的采集与可视化分析(scrapy+mysql+matplotlib+flask)
  • Cursor的简单使用
  • 【模型】RNN模型详解
  • 沃尔玛 礼品卡绑定 分析
  • 《 C++ 点滴漫谈: 二十四 》深入 C++ 变量与类型的世界:高性能编程的根基
  • python实现答题游戏
  • 【橘子Kibana】Kibana的分析能力Analytics之Canvas画布
  • 网站上的图片无法使用右键“图片另存为”
  • 步入响应式编程篇(三)之spring webFlux与R2DBC
  • 力扣算法题——611.有效三角形的个数
  • Java 大视界 -- Java 大数据在元宇宙中的关键技术与应用场景(65)
  • 如何运用python技术搭建一个导航网站?
  • 关于安卓compose在gradle8.0上,版本依赖的问题
  • Pyecharts之图表样式深度定制
  • ubuntu无法上网的解决办法
  • 【漫话机器学习系列】061.线性回归参数计算(Finding Linear Regression Parameters)
  • 智能交互革命:论UI-TARS技术突破与未来图景
  • AI刷题-最小化团建熟悉程度和
  • 【java数据结构】HashMapOJ练习题
  • vim的多文件操作
  • 【Rust自学】15.1. 使用Box<T>智能指针来指向堆内存上的数据
  • docker入门——多用户服务器管理(小白)
  • 实战网络安全:渗透测试与防御指南
  • 汽车行业敏捷转型的推动者:ScrumCN的优势与实践