C Note(NO.5)

存储器中的一个字节称为一个内存单元,内存单元的编号也叫做地址,据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。
在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。
指针”是指地址,是常量,“指针变量”是指取值为地址的变量。
凡是出现数组,函数的地方都可以用一个指针变量来表示,只要该指针变量中赋予数组或函数的首地址即可。这样做,将会使程序的概念十分清楚,程序本身也精练,高效。

变量的指针就是变量的地址。存放变量地址的变量是指针变量。即在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个变量的地址或称为某变量的指针。在程序中用“ *”符号表示“指向”。

对指针变量的定义包括三个内容:
(1) 指针类型说明,即定义变量为一个指针变量;
(2) 指针变量名;
(3) 变量值(指针)所指向的变量的数据类型。

其一般形式为:类型说明符 *变量名;其中, *表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。例如: int *p1;表示 p1 是一个指针变量,它的值是某个整型变量的地址。一个指针变量只能指向同类型的变量。

两个有关的运算符:
1) &:取地址运算符。
2) *:指针运算符(或称“间接访问” 运算符)。
int a;
int *p=&a;
1. 指针运算符
 1) 取地址运算符&:取地址运算符&是单目运算符,其结合性为自右至左,其功能是取变量的地址。
 2) 取内容运算符*:取内容运算符*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在*运算符之后跟的  变量必须是指针变量。
需要注意的是指针运算符*和指针变量说明中的指针说明符*不是一回事。在指针变量说明中, “*”是类型说明符,表示其后的变量是指针类型。而表达式中出现的“*”则是一个运算符用以表示指针变量所指的变量。
 2. 指针变量的运算

a. 把数组的首地址赋予指向数组的指针变量。
例如:
int a[5],*pa;
pa=a;
(数组名表示数组的首地址,故可赋予指向数组的指针变量 pa)
也可写为:
pa=&a[0]; /*数组第一个元素的地址也是整个数组的首地址, 也可赋予 pa*/
当然也可采取初始化赋值的方法:
int a[5],*pa=a;
b. 把字符串的首地址赋予指向字符类型的指针变量。
例如:
char *pc;
pc="C Language";
或用初始化赋值的方法写为:
char *pc="C Language";
这里应说明的是并不是把整个字符串装入指针变量,而是把存放该字符串的字符数组的首地址装入
指针变量。在后面还将详细介绍。
c. 把函数的入口地址赋予指向函数的指针变量。
例如:
int (*pf)();
pf=f; /*f 为函数名*/
3. 两个指针变量之间的运算:只有指向同一数组的两个指针变量之间才能进行运算,否则运算毫无意义。
① 两指针变量相减:两指针变量相减所得之差是两个指针所指数组元素之间相差的元素个数。实际上
第 147 页
是两个指针值(地址)相减之差再除以该数组元素的长度(字节数)。

② 两指针变量进行关系运算:指向同一数组的两指针变量进行关系运算可表示它们所指数组元素之间
的关系。
 

整型二维数组 a[3][4]

a 是二维数组名, a 代表整个二维数组的首地址,也是二维数组 0 行的首地址,a[0]是第一个一维数组的数组名和首地址,*(a+0)或*a 是与 a[0]等效的, 它表示一维数组 a[0]0 号元素的首地址,&a[0][0]是二维数组 a 的 0 行 0列元素首地址,因此, a, a[0], *(a+0), *a, &a[0][0]是相等的。同理, a+1 是二维数组 1 行的首地址,等于 1008。 a[1]是第二个一维数组的数组名和首地址,&a[1][0]是二维数组 a 的 1 行 0 列元素地址,也是 1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的,由此可得出: a+i, a[i], *(a+i), &a[i][0]是等同的。此外, &a[i]和 a[i]也是等同的,a[i], &a[i], *(a+i)和 a+i 也都是等同的。由 a[i]=*(a+i)得 a[i]+j=*(a+i)+j。由于*(a+i)+j 是二维数组 a 的 i 行 j 列元素的首地址,所以,该元素的值等于*(*(a+i)+j)。

 

二维数组指针变量说明的一般形式为:
类型说明符 (*指针变量名)[长度]其中“类型说明符”为所指数组的数据类型。“ *”表示其后的变量是指针类型。 “长度”表示
二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数。应注意“(*指针变量名)”两边的括号不可少,
如:int (*p)[4]

1. 字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘ \0’作为串的结束。字符数组是由于若干个数组元素组成的,它可用来存放整个字符串。
2. 对字符串指针方式
char *ps="C Language";
可以写为:
char *ps;
ps="C Language";
而对数组方式:
static char st[]={"C Language"};
不能写为:
    char st[20];
     st={"C Language"};
  而只能对字符数组的各元素逐个赋值。

在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量称为“函数指针变量”。
函数指针变量定义的一般形式为:
类型说明符 (*指针变量名)();
其中“类型说明符”表示被指函数的返回值的类型。“ (* 指针变量名)”表示“*”后面的变量是定义的指针变量。最后的空括号表示指针变量所指的是一个函数
 例如:int (*pf)();表示 pf 是一个指向函数入口的指针变量,该函数的返回值(函数值)是整型。

 

在C语言中允许一个函数的返
回值是一个指针(即地址),这种返回指针值的函数称为指针型函数。
定义指针型函数的一般形式为:
类型说明符 *函数名(形参表)
{
…… /*函数体*/
}
其中函数名之前加了“ *”号表明这是一个指针型函数,即返回值是一个指针。类型说明符
表示了返回的指针值所指向的数据类型。
如:
int *ap(int x,int y)
{
...... /*函数体*/
}
表示 ap 是一个返回指针值的指针型函数,它返回的指针指向一个整型变量。
int (*p)()是一个变量说明,说明 p 是一个指向函数入口的指针变量,该函数的返回值是整型量, (*p)的两边的括号不能少。
int *p()则不是变量说明而是函数说明,说明 p 是一个指针型函数,其返回值是一个指向整型量的指针, *p 两边没有括号。作为函数说明,在括号内最好写入形式参数,这样便于与变量说明区别。对于指针型函数定义, int *p()只是函数头部分,一般还应该有函数体部分。

一个数组的元素值为指针则是指针数组。 指针数组是一组有序的指针的集合。 指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。指针数组说明的一般形式为:
   类型说明符 *数组名[数组长度]

其中类型说明符为指针值所指向的变量的类型。
 例如:
int *pa[3]
表示 pa 是一个指针数组,它有三个数组元素,每个元素值都是一个指针,指向整型变量。

 

二维数组指针变量是单个的变量,其一般形式中"(*指针变量名)"两边的括号不可少。而指针数组类型表示的是多个指针(一组有序指针)在一般形式中"*指针数组名"两边不能有括号。
例如:
        int (*p)[3];
表示一个指向二维数组的指针变量。该二维数组的列数为 3 或分解为一维数组的长度为3。
        int *p[3]
表示 p 是一个指针数组,有三个下标变量 p[0], p[1], p[2]均为指针变量。 如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。通过指向指针的指针变量来访问变量则构成“二级间址”。
 

char **p;
p 前面有两个*号,相当于*(*p)。显然*p 是指针变量的定义形式,如果没有最前面的*,那就是定义了一个指向字符数据的指针变量。现在它前面又有一个*号,表示指针变量 p 是指向一个字符指针型变量的。 *p 就是 p 所指向的另一个指针变量。

C语言规定 main 函数的参数只能有两个,习惯上这两个参数写为 argc 和 argv。因此, main 函数的函数头可写为:
main (argc,argv)
C语言还规定 argc(第一个形参)必须是整型变量,argv( 第二个形参)必须是指向字符串的指针数组。加上形参说明后, main 函数的函数头应写为:
main (int argc,char *argv[])
由于 main 函数不能被其它函数调用,因此不可能在程序内部取得实际值。
 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章