指针
指针变量就是保存地址的变量
int i;
int*p=&i;
int *q;
q=p;//指针p和q都指向了i,修改*p或者*q都可以改变量i的值
一般形式: 类型名 *指针变量名;
- 类型名指定指针变量所指向变量的类型
- 指针声明符*在定义指针变量时被使用,说明被定义的那个变量是指针
- 一旦指针被定义并赋值后,就可以如同其他类型变量一样赋值运算,如*p和*q可以p=q;
- p里面的值就是i的地址,就称为p指向了i
变量的值是内存的地址
- 普通变量的值是实际的值
- 指针变量的值是具有实际值的变量的地址
作为参数的指针:
- void f(int *p);在被调用的时候,得到某个变量的地址
- int i=0; f(&i);在函数里面可以通过这个指针访问外面的这个i
#include<stdio.h>
void f(int *p);
int main(void)
{
int i=6;
printf("&i=%p\n",&i);
f(&i);//输入i的地址
printf("i=%d\n",i);
return 0;
}
void f(int *p)//定义一个指针变量
{
printf("p=%p\n",p);//此时p为i的地址
printf("*p=%d\n",*p);//此时*p为i的值
*p=26;//指针变量将26赋回i里面
}
//
&i=000000000065FE1C
p=000000000065FE1C
*p=6
i=26
*p即是等于i(等于所指向的变量的值),p即是i的地址(等于指向的变量的地址)
*是一个单目运算符,用来访问指针的值所表示的地址上的变量
可以做右值也可以做左值: int k=*p *p=k+1
指针的使用
- 指针应用场景一:在函数里面交换两个变量的值
swap(&a,&b);
void swap(int *a,int *b)
{
int t=*a;
*a=*b;
*b=t;
}
- 指针应用场景二:函数需要返回多个值,某些值只能通过指针返回(场景一同理)
传入的参数实际上是需要保存带回的结果的变量
PS:指针没有得到变量的地址之前不能使用
指针,数组和地址间的关系:
- 数组名本身是一个地址,即是指针值,但数组是指针常量,而不是变量。因此不能出现对数组a[]的a赋值
- 由于a+i是距数组a的基地址的第i个偏移,所以*(a+i)与a[i]等价
由此可见,数组名可以使用指针形式,而指针变量可以转换为数组形式
- a[]是变量,a是指针,*p是被指向变量,p是指针。
- 指针得到变量的地址方式:*p=&变量或p=指针或p=a[0]
- f(a)=f(&a[0])后者传入数组首地址进入函数,函数里面有了a[0]的地址。因为数组的地址是连续的,需要a[1]时,对a+1即得
#include<stdio.h>
int f(int a[])//定义了一个指针 ,a[]等价*a等价a[9]
{
int i;
for(i=0;i<9;i++){
printf("%d\n",a[i]);
}
return 0;
}
int main(){
int a[9]={0};
a[1]=3;
//a[]是变量的值 ,a是指针
f(a);//等价于f(&a[0]);
}
int a[100],*p;
p=a;//将数组(指针常量)a[0]的地址赋给*p
p=&a[0];//与上式等价
//等价
p=a+1;
p=&a[1];
p++;
当指针加上const时:
- const在 * 后面,表示该指针得到了某个变量的地址,不能再指向其他变量,但可以修改该变量值
例:int * const q=&i;表示指针q固定指向i,不能q++或*q=&a,
- const在 * 前面,表示不能通过这个指针去修改被指向的变量,但可以修改指向其他变量
例:const int *q=&i;不能*p=26,但可以i=26
const int a[]={1,2,3,4,5,6},数组变量已经是const的指针,必须通过初始化进行赋值
- 保护数组值:数组传入函数时传递的是地址,因此函数可以修改该数组的值
int f(const int a[] );给数组加上const,数组便是不可修改的状态,以保护数组不被函数破坏
指针运算:
- 给一个指针加1表示要让指针指向下一个变量
int a[10];
int *p=a;
*(p+1)-----a[1]
注意:如果指针不是指向一片连续分配的空间(数组),则这种运算没有意义
- 指针加减(+,+=,-,-=)
- 递增递减(++/--) *p++表达:先取出p所指的数据,完事之后再把p移到下一个位置去
- 两个指针相减,求出两个地址之间能放多少个相同类型的值
- 指针比较<,<=,==,>,>=,!= 比较它们在内存中的地址
0地址:
当然你的内存中有0地址,但是0地址通常是个不能随便碰的地址
*p=NULL;或者*p=0;(有的编译器不认0为0地址)
用0地址表示特殊的事情:
- 返回的指针是无效的
- 指针没有被真正初始化(先初始化为0)
指针的类型:
- 无论指向什么类型,所有的指针大小都是一样的
- 指向不同类型的指针是不能直接互相赋值的,为了避免用错指针
- 但可以做指针的类型转换:
int *p=&i; boid*q=(void*)p; 这并没有改变p所指的变量i的类型,而是让后人用不同的眼光通过p看i
PID控制系统
比例控制P
控制量与误差成正比
可以减小误差,产生响应速度和力度,过小响应慢,过大会产生振荡,造成稳态误差
积分控制I
累计误差并直接加到控制量上(积分误差函数),提供了一定的惯性
在系统误差和外力作用时消除偏差、提高精度,同时也会增加响应速度,产生过冲,过大会产生振荡
微分控制D
计算当前误差的变化率并加至控制量,提供一定的阻尼提高抗干扰性
抑制过冲和振荡,过小系统会过冲,过大会减慢响应速度,另一作用为抵抗外界的突发干扰,阻止系统的突变。
微分调解检测的是瞬时信号,D对高频信号有放大作用
先调整P,从小到大
再调整I,最后可以微量加一点D以平稳曲线