发表
2008年2月19日(最后更新:2008年2月19日)

指针

评分:4.0/5(26票)
*****
注意:这仅仅是因为很多初学者需要掌握这个概念。

它是什么
----------

指针是地址。它们可以被赋值,或者被设置为“指向”另一个内存位置。它们是一个强大的概念,但被许多C语言用户所误解。它们的使用可以使代码更高效、更易读、功能更强大。

如何使用它
-------------

指针的声明使用以下模板(假设T是一个类型)
 
T *var;

当然,有些人更喜欢以下约定
 
T* var;

但这些修改属于用户个人观点,因为编译器会忽略声明中的空格(除非它们分隔了类型和第一个变量)。

普通变量的地址可以像这样赋值给指针
1
2
3
T *ptr;
T var;
ptr=&var;

这是有效的,因为“与”号(&)会获取变量的地址,并将该值赋给指针,而指针本身就存储着一个地址。

可以创建指向指针的指针。也可以创建指向这些指针的指针,但它们很少有用。

星号(*)可以解引用指针。
1
2
3
4
5
6
T *ptr;
T var, var2;
ptr=&var;

var2=*ptr;
*ptr+=var2;


最后两行语句有效地将var2赋值为var的值(因为解引用运算符指示机器跟随指针指向变量),然后将var2加到var上(相当于将var翻倍)。由于解引用的指针与var指向同一个位置,因此对解引用的指针的所有操作都会影响它所指向的变量。

通常,为了表示不指向任何东西的状态,指针会被赋值为0。这个指针就是空指针。解引用空指针是非法的。

可以通过在声明的星号前加上关键字const来声明常量指针
 
T const *var;


不要将此与以下代码混淆
 
const T *var;

这定义了一个变量var,它指向一个常量T类型。常量指针必须被初始化。事实上,数组就是常量指针。

为指针分配的空间是容纳内存地址所需的空间。这通常是一个无符号长整型。

指针可以重定向到多个目标。例如
1
2
3
4
5
6
7
8
T *ptr;
T var, var2;

ptr=&var;
//Do some stuff with var

ptr=&var2;
//Do some stuff with var2 


指针有自己的算术运算:加或减一个值(比如X)实际上会导致地址偏移X*sizeof(T)。这就是数组解引用的方式(表达式a[x]实际上是*(a+x),这之所以有效是因为数组是常量指针)。不允许乘法和除法。

指向任何任意类型T的指针必须声明为T * 或特殊类型void *。void指针(不要与空指针混淆)可以被赋给任何类型的值的地址。因此,void指针的指针算术和解引用都是非法的。然而,你可以对强制转换后的void指针进行解引用和算术运算。

指针定义不会隐式地扩展到声明中的每个成员,你需要为每个指针变量加上星号。

你为什么需要它们
-----------------

数组,数组,数组!!!每个数组都是一个常量指针,因此拥有这项功能非常重要。

函数通常传递参数的副本。通过传递地址(并将函数定义为接收指针),可以修改调用者的值。这种传递方式称为引用传递。

指针对于字符串处理至关重要。每个C字符串都是一个字符数组,因此是一个指向字符的常量指针。

在创建链表和使用动态内存分配时也需要它们。使用指针进行动态内存分配意味着你可以
-使用同一个指针指向多个独立的内存空间。
-将此值赋给任何其他相同类型或void *的指针。
-定义一个任意长度的范围来由单个指针管理。这是数组的基础。

深入学习
-------------

继续,试试几个指针操作。请记住,你需要强制转换void指针才能使用它。

指针在多个场合被内部使用。没有一个程序不包含指针,因为函数就是指向它们在数据段中编译代码的指针(是的,包括main函数)。寻找其他类似的用途。

您的回复非常有价值!请在下方提出您的问题和评论!
谢谢,
Graham Northup