我想要一种语言,只需对它说我要干什么就行
1.
理解指针的第一步是在机器级上观察指针表示的内容。大多数现代计算机将内存分割为字节(byte),每个字节可以存储8位的信息。
每个字节都有唯一的地址(address),用来和内存中的其他字节相区别。如果内存中有n个 字节,那么可以把地址看作0~n-1的数。
地址 内容
可执行程序由代码(原始C程序中与语句对应的机器指令)和数据(原始程序中的变量)两部分构成。程序中的每个变量占有一个或多个字节内存,把第一个字节的地址称为变量的地址。下图中,变量i占有地址为2000和2001的两个字节,所以变量i的地址是2000:
这就是指针的出处。虽然用数表示地址,但是地址的取值范围可能不同于整数的范围,所以一定不能用普通整型变量存储地址。但是,可以用特殊的指针变量(pointervariable)存储地址。在用指针变量p存储变量i的地址时,我们说p“指向”i。Q&A换句话说,指针就是地址,而指针变量就是存储地址的变量。
这里不再把地址显示为数,而是采用更加简单的标记。为了说明指针变量p存储变量i的地址,把p的内容显示为指向i的箭头:
指针变量的声明
对指针变量的声明与对普通变量的声明基本一样,唯一的不同就是必须在指针变量名字前放置星号:
int*p;
上述声明说明p是指向int类型对象的指针变量。这里我们用术语对象来代替变量,是因为p可以指向不属于变量的内存区域。
指针变量可以和其他变量一起出现在声明中:
inti,j,a[10],b[20],*p,*q;
在这个例子中,i和j都是普通整型变量,a和b是整型数组,而p和q是指向整型对象的指针。
C语言要求每个指针变量只能指向一种特定类型(引用类型)的对象:
int*p;/*pointsonlytointegers*/double*q;/*pointsonlytodoubles*/char*r; /*pointsonlytocharacters*/
至于引用类型是什么类型则没有限制。事实上,指针变量甚至可以指向另一个指针,即指向指针的指针。
2.取地址运算符和间接寻址运算符
为使用指针,C语言提供了一对特殊设计的运算符。为了找到变量的地址,可以使用&(取地址)运算符。如果x是变量,那么&x就是x在内存中的地址。为了获得对指针所指向对象的访问,可以使用*(间接寻址)运算符。如果p是指针,那么*p表示p当前指向的对象。
取地址运算符
声明指针变量是为指针留出空间,但是并没有把它指向对象:
int*p; /*pointsnowhereinparticular*/
在使用前初始化p是至关重要的。一种初始化指针变量的方法是使用&运算符把某个变量的地址赋给它,或者更常采用左值:
inti,*p;
...
p=&i;
通过把i的地址赋值给变量p的方法,上述语句把p指向了i:
Q&A:在声明指针变量的同时对它进行初始化是可行的:
inti;
int*p=&i;
甚至可以把i的声明和p的声明合并,但是需要首先声明i:
inti,*p=&i;
间接寻址运算符
一旦指针变量指向了对象,就可以使用*运算符访问存储在对象中的内容。例如,如果p
指向i,那么可以显示出i的值,如下所示:
printf('%d\n',*p);
Q&A printf函数将显示i的值,而不是i的地址。习惯于数学思维的读者可能希望把*想象成&的逆运算。对变量使用&运算符产生指向变量
的指针,而对指针使用*运算符则可以返回到原始变量:
j=*&i; /*sameasj=i;*/
只要p指向i,*p就是i的别名。*p不仅拥有和i相同的值,而且对*p的改变也会改变i的值。(*p是左值,所以对它赋值是合法的。)下面的例子说明了*p和i的等价关系,这些图 显示了在计算中不同的点上p和i的值。
p=&i;
i=1;
printf('%d\n',i); -> /*prints1*
/printf('%d\n',*p); -> /*prints1*/
*p=2;
printf('%d\n',i); -> /*prints2*
/printf('%d\n',*p); -> /*prints2*/
注意
不要把间接寻址运算符用于未初始化的指针变量。如果指针变量p没有初始化,那么试图
使用p的值会导致未定义的行为:
int*p;
printf('%d',*p);/***WRONG***/
给*p赋值尤其危险。如果p恰好具有有效的内存地址,下面的赋值会试图修改存储在该地址的数据:
int*p;
*p=1;/***WRONG***/
如果上述赋值改变的内存单元属于该程序,那么可能会导致出乎意料的行为;如果改变的内存单元属于操作系统,那么很可能会导致系统崩溃。编译器可能会给出警 告消息,告知p未初始化,所以请留意收到的警告消息。
3.指针赋值
C语言允许使用赋值运算符进行指针的复制,前提是两个指针具有相同的类型。假设i、j、 p和q声明如下:
inti,j,*p,*q;
语句
p=&i;
是指针赋值的示例,把i的地址复制给p。下面是另一个指针赋值的示例:
q=p;
这条语句是把p的内容(即i的地址)复制给q,效果是把q指向了p所指向的地方:
现在p和q都指向了i,所以可以用对*p或*q赋新值的方法来改变i:
*p=1;
*q=2;
任意数量的指针变量都可以指向同一个对象。注意不要把
q=p;
和
*q=*p;
搞混。第一条语句是指针赋值,而第二条语句不是。就如下面的例子显示的:
p=&i;q=&j;i=1;
*q=*p;
赋值语句*q=*p;是把p指向的值(i的值)复制到q指向的对象(变量j)中。