指针
1. 数组名是指针常量。实参数组名是指针常量,形参数组名是指针变量,在函数调用开始时,它的值等于实参数组首元素的地址,在函数执行期间,可以被再赋值。
2. 形参数组名实际上是一个指针变量。并不是真正的开辟一个数组空间,所以可以不指定数组元素的个数。
定义实参数组时必须指定数组大小,因为要开辟相应的数组空间。
3. a[i]和*(a+i)是等价的。二维数组中*(a+i)不是指“a+i所指单元中的内容”,而是指“a+i行第0列元素的地址”。
4. 数组指针:二维数组中,在指向行的指针前面加一个*(降级)就转换为指向列的指针;在指向列的指针前面加&(升级)就成为指向行的指针。 &a[i]=&*(a+i)=a+i指向行,而a[i]=*(a+i)指向列。
int (*p)[4] 用指针变量做形参,所处理的数组的大小可以变化。
5. 指针数组:int *p[4] 一般用于指向若干个字符串。各个字符串的长度可以不同,节省内存单元;方便对字符串进行排序,不必改变字符串的位置,只需改动指针数组中各元素的指向(即改变各元素的值)即可。
1
|
void main( int agrc, char *argv[]) |
利用指针数组做函数的形参,可以向程序传送命令行参数(这些参数是字符串),这些字符串的长度事先并不知道,而且各参数字符串的长度一般并不相同,命令行参数的数目也是任意的。用指针数组能很好满足以上要求。
1 #include <iostream.h>
2 #include <stdio.h>
3 int main ()
4 {
5 char *a[]={"hello","the","world"};
6 char **P=a;
7 P++;
8 cout << P << endl; //0x0012FF78 指向数组指针的指针
9 cout << *P << endl; //the 数组中的字符指针,直接输出该字符指针所指的字符串!*****!!
10 cout << **P << endl; //t 字符指针指向的某一个字符的值(注意与列指针的区别)
11
12 int c[2][3]={1,2,3,4,5,6};
13 int (*pc)[3];
14 pc = c;
15 cout << pc << endl; //0x0012FF58 行指针,行指针不能输出一整行的数据,字符指针可以!!****!!
16 cout << *pc << endl; //0x0012FF58 列指针,指向某一特定元素
17 cout << **pc << endl; //1 指针的值
18 return 0;
19 }
遇到字符指针时,会将其当作字符串名处理,输出字符指针所指的整个字符串!这是与行指针的很明显的区别!!!
6. 函数指针:指向函数的指针,即指向函数入口地址的指针,通过该指针变量就可以调用此函数。
用指向函数的指针作函数参数,可以在被调用函数中灵活的使用实参函数,因为要调用的函数作为形参不是固定的。增加了函数使用的灵活性。
7. 指针函数:返回指针值的函数。返回的指针所指向的数据不能够是函数内声明的变量(存在于栈内),因为函数内的变量在函数执行完会自动释放。
使用栈内存返回指针是明显错误的,因为栈内存将在调用结束后自动释放,从而主函数使用该地址空间将很危险。
例如:
1
2
3
4
5
6
7
8
9
10
11
|
char * GetMemory() { char p[] = "hi" ; //存在栈内存中 return p; } void main() { char *str = GetMemory(); //出错! 得到一块已释放的内存 printf (str); } |
使用堆内存返回指针是正确的,但是注意可能产生内存泄露问题,在使用完毕后主函数中释放该段内存。
例如:
1
2
3
4
5
6
7
8
9
10
11
|
char * GetMemory() { char *p = new char [100]; //存在堆内存中 return p; } void main() { char *str = GetMemory(); delete [] str; //防止内存泄露! } |