指针

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;       //防止内存泄露!
}
原文地址:https://www.cnblogs.com/fuleying/p/4455380.html