C语言笔记之指针

来源:互联网 发布:qq五笔 for mac 编辑:程序博客网 时间:2024/05/17 07:08

1.未初始化和非法的指针
下面的代码段说明了一个极为常见的错误:
int *a;

*a = 12;
这个申明创建了一个名为a的指针变量。但是a究竟指向哪里?我们申明了一个变量,但却没有对他初始化,所以我们没有办法预测12这个值将会存储与什么地方。
指针变量和其他变量没有区别。如果变量是静态的,那么它会被初始化为0.但如果变量是自动的,它根本不会被初始化。无论哪种情况,申明一个指向整形的指针都不会“创建”用于存储整形值的内存空间。

如果程序执行赋值操作,如果运气好的话,a会被分到一个非法地址,这样赋值语句就会出错,程序会终止。在Unix系统上这个错误被称为“segmentation violation” 或者”memory fault”,在windows的PC上,对未初始化或非法指针进行间接访问操作是一般保护性异常的根源之一。

更加严重的情况是:这个指针可能包含了一个合法的地址,接下来的事很简单:那个位置上的值会被修改,虽然你可能无意修改它,但是这种类型的错误很难捕捉。
在对指针间接访问之前,必须非常小心,确保它们已经被初始化!

2.NULL指针
NULL指针是一种特殊的指针变量,不指向任何东西。
要使一个指针为NULL指针,可一个它赋值0。判断一个指针变量是不是NULL指针,可以将它和0比较,这是一种源代码约定。就机器内部而言,NULL指针的实际值可能与此不同,编译器负责0值和内部值的转化。

NULL指针的概念很有用,它给你一种方法去表示特定的指针不指向任何东西。例如,假如某个函数的目的是查找数组中是否有某个值,如果数组不包含这个特定的值,那么返回值可以为NULL。这样的技巧允许函数的返回值包含两个不同片段的信息。首先,有没有找到元素? 如果找到了,元素是哪个?(这个技巧在C语言中用得很多,但是这违背了软件工程的原则,用一个单一的值表示两个不同的意思是一件危险的事,因为将来很容易无法弄清楚哪个才是它的用意。更好的方法是让函数返回两个独立的值:首先是个状态值,用于提示是否成功;其次是个指针,当状态值提示查找成功时,指针指向的值就是要查找的元素。)

对NULL 指针的解引用操作是违法的。在有些机器上,它会访问内存位置0,机器不会妨碍你访问或修改这个位置,这会造成难以寻找的错误。在其他机器上,这会应引发一个错误,并终止程序(linux系统上会返回segmentation fault)。

对所有指针变量进行显示的初始化会是一个很好的做法,如果你知道这个指针变量指向哪里,就把它初始化为该地址,否则就指向NULL。

3.指针,间接访问和变量
*&a = 25 表示什么?
答案是把值25赋值给变量a。&操作符产生a的地址,它是一个指针常量。
不过大概没有人会这么写,因为它和a=25其实是一个效果。
4.指针常量
假设变量a存储于位置100,下面这个表达式是合法的吗?
*100 = 25
看上去像是把25赋值给a,但是实际上这是非法的。间接访问操作只能用于指针类型的表达式。假如你确实要把25存储与位置100,那必须使用强制类型转换:
(int ) 100 = 25;
不过使用这个表达式的机会几乎是没有的,因为你通常无法预测编译器会把某个特定的变量放在内存的什么位置。
5.指针的指针
int a = 12;
int *b = &a;
int **c = &b;
c就是一个指向指针的指针。这是合法的,指针变量和其他变量一样,占据内存中的某个特定的位置。所以用&操作符取它的地址是合法的(申明为register的变量除外,具体看C语言存储类型)。

6.int* a; 和 int *a;哪种是更好的表达方式?一般来说都会觉得前者是更好的方式。但是实际上后者会更好一点。原因如下:
int* a,b,c;
这句定义达到了什么效果?习惯了前者的表达方式会让你觉得这句定义了三个指针变量,但是实际上不是,这句中*是b的一部分,只有b被声明为指针,其余两个为普通变量。如果你想要声明三个指针变量,正确的写法是:
int *a,*b,*c;

几点小结
指针就是值表示内存地址的变量。
类型是通过值的使用方法隐式地确定的。编译器能够保障值的声明和值的使用之间的关系是适当的,从而帮助我们确定值的类型。
声明一个指针变量并不会自动分配任何内存。在对指针进行间接访问前,指针必须初始化。

0 0
原创粉丝点击