C和指针

来源:互联网 发布:淘宝人群画像在哪里 编辑:程序博客网 时间:2024/06/12 14:44

C和指针

 

在C中有一个很重要的概念,或许大家都知道,那就是指针。在很多初学者刚接触C的时候都认为这是最难的知识点了。没错,我刚开始学的时候也是这么想的,上了第一节课后,第一感受就是:天啊,这简直就是天书!由于个人对于C的爱好,经过一段时间的学习和研究之后,发现这一块是我最喜欢的,并且逐步发现这也是本人的强项之一了(呵呵,有点夸耀自己了!).

大家谁都知道,至真是很有效的表示许多复杂的数据结构,比如队列,链表,树和图等,因此熟练掌握指针和正确使用指针对程序员来说是至关重要的。至少我到现在还没听说过有哪位c程序员不用掌握指针的。

的确,对于初学者来说,至真是很难的,至少是非常难入门的。其实,就个人感觉来说,指针还是比较简单的。只要把握了本质是不难掌握它的,甚至是运用自如(不过本人还没达到这水平)。

下面就如下几个知识点来说明简单谈谈个人对于指针的学习感受和认识。
1、内存和地址

正如大家知道的,每个变量在内存中都占有一定的存储单位,每种语言都是这样的。c编译程序在对程序编译时,根据程序中的变量类型,在内存中为其分配相应的存储空间,而变量在内存中的首地址,就是该百年量的地址,同时,在这块内存地址中的数据就是变量内容。所以如果声明没有初始值的变量时,那么它们的内容是随机的,不确定的。
打个比方,比如一条街道上,有一排的房子,那么每间房子都有它的固定的门牌号。而每间房子也拥有它的房主。所以当你要寻找一位朋友或者商业合作伙伴(这就是你要的变量),那么你可以直接按照他给你的门牌号(相当于变量的地址)接找到你的朋友,或许你手中有一个门牌号,你需要确认房主(地址中的内容),那么你可以到这间房子,然后敲门问:“请问是张生家吗?”。
通过上面的例子,或许大家都明白了,通过指针查找变量的数据,时间上就相当于,你去一间房子询问主人是谁或者找这位主人。

2、指针的类型

通过第一点的讲解大家都明白了指针的含义,那么指针的类型是什么呢?大家都知道数据是有类型的,同样,指针也是有类型的,它与数据的类型是一致的。一个地址中存放着一个数据,这个数据或许是int,double或者是char,二地址是与这个地址所存的内容以对应的,所以指针的类型就是数据的类型。同样是上面的例子。房子的特点与主人的特点是一致的,有的趋于时尚,那么房子也毫不例外的被时尚的元素所装扮,而趋于稳重的女士或者先生,他的房子也被一些体现稳重的因子所包围。有这一点可知,如果一块内存存储的是int那么对应着这块内存的指针就是int型。由此可以至少得出以下结论:
A:同一个地址在不同时候可以存储不同类型的数据。具体被解释为什么数据类型,这取决他被使用的方式,如果是整数指令,那么这个植被解释为整数,如果使用的是浮点指令,那么就被解释为浮点数。同样,由此结论有可引出另一条重要的结论:不能简单的通过检查一个值的未来判断它的比如有个二进制形式表示的32位值:

01100111011011000110111101100010

下面是这些位被解释的几种结果:
类型                      值
1个32位整数              1735159650
2个16位整数              26476和28514
4个字符                  glob
浮点数                   1.116533*10e24

B:在一个内存中可以存放一个指针,意思就是一个指针可以指向另一个指针,这就是指针的指针。这一点在后面讲述。

现在请看下面的例子:

typedef struct
{
   int a;
   double b;
   struct student c;
}STR;

这里定义了一个结构体。有下面的声明语句:
STR  _a:
STR  *b;
b=&_a;

很明显b指向变量_a所在的地址的首地址,即&_a.a,但是下面的引用却是错误的:
b=&_a.a;
为什么呢?回到上面的知识。b的指针类型是数据类型STR,而&_a.a的类型是int,所以,虽然他们是同一个地址,确实不同的类型!!!
这一点很让新手常常困惑:明明我调用的是同一个地址,为什么老是出错呢?!刚开始时我也是这样,常常不注意指针的类型,或许很多新手像我当初一样根本就没听说指针还有类型!!!

3、未初始化和非法的指针

下面是一段那许多新手都犯的错误,一些老手也是时常不经意犯的错误.
int *a;
/*中间代码*/
*a=1;
这个声明创建了一个a指针变量,随后将1存储在a所指向的内存中。但是这段代码是有BUG的。从上面我们声明了a但是他指向哪里呢?我们不知道,因为我们没对他初始化!所以我们也不知道1存储到那个位置去了!如果你运气好,a的初始值是个非法地址,程序会报错,而中断程序。如果不幸的话,这个指针可能包含一个合法的地址,那么他会覆盖原先这个地址的内容将它改为1,也就是说,当下次你再次访问他时,它的内容就不是原先的内容了,而1!这就是脏数据!而这个指针就是非法指针!
所以未初始化的指针往往是这种错误,这是一种非常隐蔽的错误!很难查找。如果你不懂的这一点那么你会被他整的疯!!!

4、指针的指针
在第二点我们提到过指针的指针。那么他是怎么会是呢?
先看看下面的声明语句:
int a=1;
int *b=&a;

这个声明是说将b指向a变量所在的内存地址。那么再看下面的语句:
int a=1;
int *b=&a;
int **c=&b;

语句中c就是指针的指针。下面我们来解释一下它的含义。*操作符具有从右向左的结合性,所以这个表达式相当于*(*c),那么我们必须从里逐层求值。*c访问c所指向的位置,我们知道这是变量b。第二个间接访问符访问这个位置所指向的地址,也就是变量a。所以按照这种想法,指针的指针并不难懂,只要你留心所有的箭头。

讲这么多感觉也差不多了。总的来说指针的基本知识点也就这些了,这些是非常基础的,通常也是最难的。然而不论怎样只要你时时注意指针的运用,并且有意识的制造某些错误,那么经过这些锻炼,你会感觉自己大有长进。真心祝愿新手们能够领会指针的强大功能!

原创粉丝点击