Lesson 12 指针2

本文讲解了指针的变量大小计算、类型意义、运算规则(包括指针加减整数和指针间元素计算),以及const修饰指针的含义。还探讨了野指针的成因,并通过实例演示了字符串左旋的实现方法。

指针2

这节课继续讲指针相关的知识。

指针变量大小的计算

使用sizeof就可以计算出指针变量的大小。但其实没必要,指针变量的大小是根据环境来的,32位机器就是32bit,4个Byte,64位则是8个Byte。这里也可以理解寻址空间为什么和位数有关。
这里一定要注意,指针类型只是决定指针指向数据的类型,并不是说不同类型的指针变量就必须占用不同的空间。

指针类型的意义

指针类型决定了指针访问内存的方式。
看一下代码:

//代码1
int n = 0x11223344;
int* pi = &n;
*pi = 0;
//代码2
int n = 0x11223344;
char* pc = (char*)&n;
*pc = 0;

上述代码中,代码1是将n改成了0,代码2则是将n的第一个字节改成了0。同样的空间,由于指针类型的不同,导致最后结果的不同。

指针的运算

指针+ - 整数

指针±整数是与其类型相关的。例如一个int* 的指针+1,那么地址会+4,而一个char*类型的指针+1,地址只会+1。这也是另一个指针类型的作用。

指针-指针

这样的结果是计算两个指针之间有多少个元素。使用这种计算的时候,有两个限制:

  1. 两个指针必须是指向同一片空间;
  2. 指针类型必须一致;
    看一下代码:
int arr[10] = {0};
int* p1 = &arr[0];
int* p2 = &arr[4];
int ret = p2-p1;

这里ret的值就是4,表示arr[0]和arr[4]之间有4个元素。

指针的关系运算

指针是可以比较大小的。看一下代码:

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

上面的代码就是将数组arr中每一个元素都打印出来,注意while循环的条件使用了指针的关系运算。

const修饰指针

const修饰指针根据其位置不同,有以下两种效果:

  1. const位于*左边:修饰的对象是*p,这表示指针指向对象的值是不能被改变的;
  2. const位于*右边:修饰的对象是p,这表示指针指向的对象是不能被改变的;
    举个例子:
int m = 10;
int n = 20;
const int* p1 = &m;
*m = 0;//报错,因为*m是无法改变的
int* const p2 = &n;
p2 = &m;//报错,p2所指的对象是无法改变的

这里只看const*的相对位置,顺序是无所谓的。

野指针的成因

野指针是指指针指向的位置是不可知的。其成因有:

  1. 指针没有初始化:指针在创建后如果没有初始化,那么它指向的位置就是随机的;
  2. 指针越界访问:例如数组指针访问到数组范围之外的时候,指针就成了野指针;
  3. 指针指向空间的释放:这里看一下下面的代码。
int* test()
{ int n = 1;
	....
	return &n;
}

这里的n是函数内部的局部变量,在函数调用完成后,会释放这块空间,那么返回的&n就成了野指针。

一个小练习:字符串左旋

来源是今天的作业,字符串左旋:
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
想了不少时间。下面先说说思路:

  1. 最简单的想法就是每次左旋1个字符,循环k次。ABCD先变成BCDA然后再变成CDAB。但感觉这样效率比较低,就继续想;
  2. 经过老师的提示,可以使用这个思路。首先对字符串逆序,然后把字符串分成0~k-1k~sz-1两部分,再分别对这两部分逆序。例如想逆序ABCDEF的3个字符,先变成FEDCBA,然后变成DEFCBA,最后变成DEFABC。这个思路就比较好了,不需要多次循环,那么就可以代码实现了:
#include <string.h>
void reverse_str(char* start, char* end)
{
	while (start < end)
	{
		*start = *start ^ *end;
		*end = *start ^ *end;
		*start = *start ^ *end;
		start++;
		end--;
	}
}

void left_votex(char* ch, int sz, int n)
{
	n = n%sz;
	char* flag = ch + n - 1;
	reverse_str(ch, ch + sz - 1);
	reverse_str(ch, flag);
	reverse_str(flag + 1, ch +sz - 1);

}

int main()
{
	char ch[] = "ABCDEF";
	printf("左旋前:%s\n", ch);
	int n = 0;
	int sz = strlen(ch);
	printf("请输入字母个数:>");
	scanf("%d", &n);
	left_votex(ch, sz, n);
	printf("左旋后:%s\n", ch);
	return 0;
}

逆序部分参考之前的字符串逆序,其余实现起来就没有那么难了。

【四轴飞行器】非线性三自由度四轴飞行器模拟器研究(Matlab代码实现)内容概要:本文围绕非线性三自由度四轴飞行器模拟器的研究展开,重点介绍了基于Matlab的建模与仿真方法。通过对四轴飞行器的动力学特性进行分析,构建了非线性状态空间模型,并实现了姿态与位置的动态模拟。研究涵盖了飞行器运动方程的建立、控制系统设计及数值仿真验证等环节,突出非线性系统的精确建模与仿真优势,有助于深入理解飞行器在复杂工况下的行为特征。此外,文中还提到了多种配套技术如PID控制、状态估计与路径规划等,展示了Matlab在航空航天仿真中的综合应用能力。; 适合人群:具备一定自动控制理论基础和Matlab编程能力的高校学生、科研人员及从事无人机系统开发的工程技术人员,尤其适合研究生及以上层次的研究者。; 使用场景及目标:①用于四轴飞行器控制系统的设计与验证,支持算法快速原型开发;②作为教学工具帮助理解非线性动力学系统建模与仿真过程;③支撑科研项目中对飞行器姿态控制、轨迹跟踪等问题的深入研究; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注动力学建模与控制模块的实现细节,同时可延伸学习文档中提及的PID控制、状态估计等相关技术内容,以全面提升系统仿真与分析能力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值