c++ 指针小计
什么时指针:指针是存入指定数据类型地址的一种变量,void * 指针类型的指针可以存放任何数据类型的指针。
定义和声名指针变量:由数据类型后跟星号,再跟随指针变量名组成。如 int *ip;指针在使用前,要进行初始化。
如int count =10;int *count = &count;如果忘记了给指针赋值是非常危险的。因为指针在没有初始化时存放的是一个随机的地址,此时如果给指针赋值(*count = 20;)是把20赋到了内存中的随机位置,因此很可能破坏系统中的另一变量甚至修改栈中的函数返回地址。
"*":此符号的用法很多,*放在可执行语句中的指针之前,称为间接引用操作符(可取出指针指向变量的值),*放在指针定义中,称指针定义符(用于定义一个指针变量)*放在表达式中用于乘法运算符,且不能放在非指针变的前面。
指针的地址:指针是变量是变量也有地址,我们可以用&取地址符取得指针变量的地址,如:int *ip = &count;用&ip得到指针变量的地址。
指针是强类型化的:给指针赋值,不但必须是一个地址,而且应该是一个与该指针类型相符的变量或常量的地址。
指针运算:指针只能用于加,减运算。
数组名称也是一个指针常量,如int a[100];中a == &a[0]的。即是数组第一个元素的地址。
指向常量的指针:在指针定义语句的类型前加const,表示指向的对象是常量。如:const int *pi=&count;(*pi指针指向的值不能修改,但是地址可以被修改,即可以将指针指向另一个常量)
指针常量:在指针定义语句的指针名前加const,表示指针本身是常量。如 int * const pi="1234";int * const pi =&count;在定义指针常量时必须初始化,且不能作为左值进行操作,但是允许修改间接访问值,即*pi = "3333";或者*pi = &pi2;
指向常量的指针常量:是指向常量的指针和指针常量的组合,它拥有两者的功能。即指针指向的值不能修改,且地址也不能被修改。如:const int * const pi=&cont
数据、字符与指针:
传递数组的指针性质:如果将一个数组作为参数传递到函数中,则在栈上定义了一个指针,可以对该指针进行递增,递减操作。由于是以指针的行式传
入则我们不能用sizeof(arr)/sizeof(*arr)的行式得到数组中的元素个数。所以必须将数组的元素个数一并传入函数内。下面是一个例子:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
将指针做为参数传递到函数可以返回多个值。由于是以指针的行式传递的,所以函数参数接收的是一个地址如果修改此地址所指向的内容,则在函数外部是可见并且是与函数内所做的修改是同步的。
例如:函数定义为 void swap(int *x,int *y);调用时则为swap(&a,&b);在函数内以*x,*y访问值。
指针函数:返回类型为指针的函数为指针函数。注意不要把在函数内部的局部变量的地址做为返回值,因为在函数内部的局部变量在函数完成时就将结
束其自已的生命周期,这样当把它做为函数的返回值时在函数外部通过返回的指针访问其值时,此值的生命已结束顾得不到想要的结果。例子如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
void 指针是空类型指针,它不指向任何类型,即void指针仅仅只是一个地址。所以空类型指针不能进行指针运算(pi++),也不能进行间接引用(*pi)
字符数组和字符常量
字符数组:char buffer[] ="helle";
字符常量:"good" 字符常量的类型是指向字符的指针(字符指针char * ),两个同样字符组成的字符串常量的地址是不相等的,且两个字符串的比较其实是两个字符串的首地址的比较。要比较内容可以用strcmp()函数进行比较。
字符指针:其实字符串常量,字符数组名都是字符指针。输出字符指针就是输出字符串,所以输入如 char *pc;pc="hello";cout <<pc;则显示hello字符串。输出字符指针的间接引用就是输出当前地址所指的单个字符。在C++中不能直接对字符数组赋值,因为数组名是一个常量指针,不能做为左值。如:char buffer[10]; buffer = "hello";是错误的。我们可使用strcpy(char * dest,const char * src);函数进行赋值。
指针数组:一个数组中的每一个元未素也都是一个指针的话,我们则称其为指针数姐。如:char *p[] = {"aaaa","bbbb","cccc"};
指向指针的指针即二级指针,指针数组是一个二级指针,如:char *pc[] = {"aaaa","bbbb","cccc"}; char **ppc=pc;
NULL指针是不指向任何地方的指针,通常用于右值。如char ch = NULL; char *pc = NULL;NULL与void * 不同,NULL是一个值,一个指针值,任何类型的指针都可以赋予该值。而void *是一种类型,是一种无任何类型的指针。
函数指针:在程序过行中,全局变量存放在Data区,局部变量存放在栈区,动态变量存放在堆区。函数代码是程序算法指令部分,它们同样也点有内存空间,存放在代码(code)区。每个函数都有地址。指向函数地址的指针称为函数指针。
函数指针的定义:int (*func)(char a,char b);此定义了一个名叫func的函数指针变量,在使用是必须指向一个指以上定义相同的返回类型和参数的函数地址,如 int fn1(char x,char y){cout <<"dddddddd";} int (*fn2)(char a,char b);通过以上定义我们就可以将函数fn1的地址赋给fn2 如 fn2=fn1;这样可以调用int c = fn2('a','b');或者int c = (*fn2)('a','b');来调用fu1函数;还可用typedef来简化函数指针的定义,如type int (*Handle)(char a,char b); 这时的Handle是一个函数指什类型,该指针类型中的指针指向一个函数,Handle不是指针变量,只是一个指针类型,通过Handle fn2;可定义一个指针变量之后可以向上面那样调用fn2 = fn1;int c = fn2('a','b');int c = (*fn2)('a','b');
另外函数针还可以构成指针数组。我们来看一个列子。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
函数指针还可以做为返回类型:如typeof int (*SIG)();typeof void (*SIGARG)(); SIG signal(int x, SIGARG sigarg){sigarg();return sigarg;}