指针应该是C语言的灵魂,通过指针能够实现很多复杂的数据结构,但是指针的使用却让很多人头疼。指针是一个非常灵活,处理字符串等高效的工具。初级C语言编程选手很少用到指针,因为指针的复杂程度让人望而却步,各种名称也非常容易让人混淆,比如指针数组,数组指针,函数指针,指向指针的指针等。但是当你真正的了解她之后,你会发现,你喜欢上她了,离不开了,哈哈~~
先说说使用指针过程中需要注意的问题:
1:检查指针有效性
指针是特殊的数据,程序中的指针必然是下面三种状态之一:①指向一个已知对象,②0值,③未初始化的指针
①:指向对象的指针,当对象的内存空间被释放的时候,该指针就指向未知对象,变成了“迷途指针”,如若后面再使用此指针将会产生异常。释放内存空间时应该将指针指向null,防止变成迷途指针。
②:0值指针间接引用可能会导致程序崩溃
一般在使用之前都要检查指针是否为空指针,避免产生错误。
③:未初始化的指针称为 野指针 ~~没有对象的指针,俗称单身狗
2:防止内存泄漏(内存泄漏是个严重的问题)
内存泄漏:当指向对象的指针被指向null后,此对象的内存泄漏,这块内存区域将不能再被访问。
3:指针类型与指向数据类型相一致
进入正题 哈哈~~
指针变量能够进行自增自减,加减,赋值运算,但是自增自减注意范围 PS:void*指针不能做算术运算
指针与指针之间还能够进行关系运算,比较大小,是否相等 等。
指针的const限定包括:指向const对象的指针和const类型的指针
①:指向const对象的指针定义 const int *p; //限定为指向const的int类型的指针 , p本身不是只读的
不能将一个const对象的地址赋值给一个非const对象的指针,但允许将一个非const对象地址赋值给const对象的指针。
②: 指向int类型的const指针 int *const p=&a //p为const指针 p=&b;//错误 p 是只读
③:指向const对象的const指针 const int pi =3; const int *const p = π指针和对象的值都无法更改。
指针与数组
1.指针可以指向一维数组和多维数组,当指向一维数组时指针代表数组首地址,当指向多维数组时指针代表行首地址
2.数组指针:一个指向数组的指针变量, int(*p)[4];//指向一维数组的指针 int(*p)[3][4];//指向二位数组的指针 数组元素为int类型
3.指针数组:数组元素为指针 int *p[4];//一维指针数组 因为[]比*优先级高 p是数组名不能做自增自减运算!!
指向指针的指针
二级指针:int **p;//存放指针变量地址的指针
一级指针存放其指向对象(该对象不是指针)的地址,二级指针的对象是指针,二级指针存放它对象的地址~~哈哈~~要是没有对象就是一个野指针,找不到回家的路了,泪目.....
在实际编程中指向指针的指针通常和指针数组结合使用,一般作为函数参数。使用指针进行数组操作会大大提高数组访问速率!
指针与字符串
初始化一个字符串时,系统会在内存中分配一个字符数组,并将字符串常量复制到其中。但初始化一个指向字符串的指针时,系统给指针分配四个字节的内存空间存放数组首地址,指向数组首地址。并且在全局数据区为字符串常量分配存储空间。通过指针来初始化字符串会节省内存开销。但是指针并不能代替数组存储大批量数据,指针只是多了一条访问数组的途径。
指针与函数
1.指针变量作为函数形参
void swap(int *p1, int *p2)
{
int t = 0;
t = *p1;
*p1 = *p2;
*p2 = t;
}
该函数实现了目标变量的交换,具体是怎么叫换的呢?假设调用函数swap(&a, &b);函数形参变量p1得到a的地址,p2得到b的地址此时p1指向a,p2指向b。*p1等价于a, *p2等价于b。函数中相当于p1 p2找到这两个地址,将地址里的数据取出来进行了肮脏的py交易。oh no ,,py这是python文件的后缀名,如果你这样说py估计写python 的程序猿会干掉你。人生苦短,我用python!!
该函数返回运算结果的前提有三个:
①:使用指针变量作为形参
②:用接受运算结果的指针作为时参调用函数
③:函数通过指针间接引用修改变量
函数中通过间接引用修改变量,避免使用全局变量
2.数组作为函数形参
double avr(double num[100],int n)
{
函数体
}
3.函数指针变量的const限定
这一点相对比较重要,如果实参是一个常量,传递到形参时一般加const限定(字符指针变量作为形参),防止在函数体内对其造成修改。
4.函数指针
指向函数的指针可以指向不同的函数,从而利用指针指向不同的函数。
#include <stdio.h>
#include <math.h>
//函数指针用法
double integral(double a, double b, double(*f)(double x))
{
int n = 1000, i=0;
double h, x, s = 0.0;
h = (b-a) /n;
for (i = 1; i <= n; ++i)
{
x = a+(i-1)*h;
s += (f(x) + f(x+h))*h/2;
}
return s;
}
double f1(double x)
{
return 1+x;
}
double f2(double x)
{
return exp(-x*x/2);
}
double f3(double x)
{
return x*x*x;
}
int main(int argc, char const *argv[])
{
double t, a, b;
//暂时没有配置scanf输入
//scanf("%lf %lf",&a, &b);
a=0;
b=1;
t = integral(a, b, f1) + integral(a, b, f2) + integral(a, b, f3);
printf("%lf\n", t);
return 0;
}
此函数功能是计算积分,通过函数指针调用不同函数来计算不同部分的积分值。
指针在C语言的编程中的使用是比较灵活的,需要经过大量编程训练才能熟练掌握。
如有疏漏,差错,欢迎指正!