深刻理解指针类型

1   内存存储

Code:
  1. char * p  = "hello,world";  

对于个语句中,p所占的内存空间是分配在栈空间中的,在变量p的生命期结束时自动释放,其中"hello,world";是存在全局的静态区的,是到这个程序才会释放的空间。当p的生命期结束后,我们将无法访问到存储"hello,world"的那块内存。所以对一下应用将会是一个错误的决定:

Code:
  1. char *strA()   
  2. {   
  3.       char str[] = "hello,world";   
  4.       return str;   
  5. }  

2 指针的内存分配应由编译器进行

我们不能随便为一个指针指定内存,那样是非常危险的,因为我们根本无法确定这个内存地址是否在使用,或是是一个很重要的内存空间。如:

Code:
  1. int *p;   
  2. p = (int*)0x8000;   
  3. *p = 2;  

将会出现执行期错误。

3 通过一个结构体来探索指针

Code:
  1. #include <iostream>   
  2. using namespace std;   
  3. struct stu   
  4. {   
  5.     int i;   
  6.     int *p;   
  7. };   
  8. int main()   
  9. {   
  10.     stu a;   
  11.     int *p = &a.i;    
  12.     p[0] = 4;   
  13.     p[1] = 5;   
  14.     cout << a.i << endl;   
  15.     cout << *(&a.i + 1) << endl;   
  16.     cout << &a.p << endl;   
  17.     cout << (&a.i + 1) << endl;   
  18.     a.p = p;   
  19.     a.p[1] = 1;   
  20.     a.p[0] = 2;//出现运行期错误   
  21.     return 0;   
  22. }  

首先我们定义了一个结构体对象a,那么现在我们就拥有了两个int型的内存,一个是为i分配的,一个是为结构体中的int型指针分配的。现在我们只有操作这两个int的内存为合法的。其他的均属于未定义行为,会引起运行期错误。

int *p = &a.i; //令p指向我们拥有的那两个int型内存的起始地址.

p[0] = 4; // ok  操作第一个int型内存 ,现在a.i = 4;

p[1] = 5; // ok 操作第二个int型内存.现在a.p中存储的应该就是5了。对此我们可以利用下面语句验证。

Code:
  1. cout << int(a.p) << endl;  

为了跟进一步的验证,我们使用了下列语句:

Code:
  1. cout << &a.p << endl;   
  2. cout << &a.i + 1 << endl;  

说明了结构体中的p所占的空间和i是连续的下一个空间。然后我们就可以通过i的内存地址来访问到p的地址。进而输出p[1];

Code:
  1. cout << *(&a.i + 1) << endl;  

 而对于程序中的:

Code:
  1. a.p = p;   
  2. a.p[0] = 2;   
  3. a.p[1] = 1;  

令a.p 存储结构体的首地址。

a.p[0] = 2; //ok 令a.i = 2;

a.p[1] = 1; //ok 令第二个可操作int空间的值为1.此时a.p = 1;

但此刻我们不能在操作a.p[0],a.p[1].否则会出现运行期错误。

4

Code:
  1. float(**def)[10];   

它是一个二级指针,指向一个指向一个含有10个元素的一位数组的指针。其实我们可以把def理解为一个三维数组名。即我们可以认为我们现在定义了一个三维数组,数组名为def。不过这个三维数组只有一行。10列。呵呵。。我们可以通过下列程序验证:

Code:
  1. float(**def)[10];   
  2. float a[10] = {1,2,7};   
  3. float (*f)[10];   
  4. f = &a;   
  5. cout << *a << endl;   
  6. cout << f[0][0] << endl;   
  7. cout << f[0][1] << endl;   
  8. cout << f[0][2] << endl;   
  9. def = &f;   
  10. cout << def[0][0][0] << endl;   
  11. cout << def[0][0][1] << endl;   
  12. cout << def[0][0][2] << endl;  

 

Code:
  1. #include <iostream>   
  2. using namespace std;   
  3. int main()   
  4. {   
  5.     float(**def)[10];       
  6.     float a[10] = {1,2,7};       
  7.     float (*f)[10];     
  8.     f = &a;   
  9.     cout << a << endl;     
  10.     cout << (*f)[0] << endl;   
  11.     cout << (*f)[1] << endl;   
  12.     def = &f;   
  13.     cout << (**def)[0] << endl;   
  14.     cout << (**def)[1] << endl;   
  15.     return 0;   
  16. }  

5

Code:
  1. double (*f[10])();  

一个函数指针数组。即f 是一个拥有10个函数指针的数组,该函数指针指向返回类型为double,参数为空的函数。

6

Code:
  1. double *(*gh)[10]  

gh 是一个指针,它指向一个一维数组,数组的元素都是double *。

7

Code:
  1. int (*(*fun)(int,int))(int);  

fun是一个函数指针,它指向含有两个int型参数并返回一个函数指针的函数。返回的函数指针类型为返回类型为int型,参数为int。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值