大家可能一看标题就觉得这有什么,不就是间接访问吗!实则不然,如果说都理解为间接访问,很多用法都没法解释,下面我们以实际例子来说明*的用法。
1. #include < stdio.h>
2. int main(void)
3. {
4. char a = 0;
5. char *p = &a;
6. char **q = &p;
7. char b[3][4] = {};
8. printf("a = %d\n", a);
9. printf("&a = %p\n", &a);
10. printf("p = %p\n", p);
11. printf("&p = %p\n", &p);
12. printf("q = %p\n", q);
13. printf("b[0][0] = %d\n", b[0][0]);
14. printf("b = %p\n", b);
15. printf("*b = %p\n", *b);
16. printf("**b = %d\n", **b);
17. a = 10;
18. *p = 11;
19. **q = 12;
20. b[0][0] = 20;
21. **b = 21;
22. printf("a = %d\n", a);
23. printf("b[0][0] = %d\n", b[0][0]);
24. return 0;
25. }
26. 运行结果:
27. a = 0
28. &a = 0xbffa2c2f
29. p = 0xbffa2c2f
30. &p = 0xbffa2c28
31. q = 0xbffa2c28
32. b[0][0] = 0
33. b = 0xbffa2c18
34. *b = 0xbffa2c18
35. **b = 0
36. a = 12
37. b[0][0] = 21
先说明第5行的*,他就不能理解为间接访问,只能理解为类型说明符,说明p是一个指向字符类型的指针变量,这是*的第1种理解。下面的第6行和第5行相同,也是类型说明符,说明一个指向指向字符类型的指针变量的指针变量,也就是2级指针,这也是*的第一种理解。
第18行的*是间接访问区别于第17行的直接访问,这是*的第2种理解。第19行可以理解为两次间接访问*(*q),都是*的第2种用法。这些都好理解。
关键是我们怎么理解*a中的*,如果把它理解为第2种用法,我们没法解释第14、15行的结果第33、34行为什么是相同的,所以不能按照第2种理解,它是*的第3种用法。怎么解释呢?首先我们必须知道b是什么类型,b肯定不是2级指针,那它是什么?b是数组指针,指向一个一维字符数组,*b的意思是指向一个一维字符数组的元素,好像听糊涂了吧,下面我们来缕一缕,指针的本质不同之处是+1的指针偏移,我们看看b+1和*b+1的指针偏移,b+1指向下一个一维字符数组,*b+1指向一个一维字符数组的下一个元素,很明显这个*的用法与第1、2种不一样,它是*的第3种理解,这下明白了吧。
通过上面的叙述,我们总结发现第19行**q和第21行**b是完全不同的两个概念,*(*q)的两个*都是第2种用法,但*(*b)的第1个*是第2种用法,第2个*是第3种用法,只有这样理解才能解释上面所说的矛盾。
*的这3种用法完全不同,大家在学习时一定要注意它们的不同,这样才能解释矛盾,同时完全理解指针应用中*的使用。