&:取地址运算符:后加变量名,给出变量的地址。
*:后加指针或者地址时,给出被指向地址中的数据。
二、指针和数组。
1、关系。
首先,数组名就是数组首元素的地址,即:flizny=&flizeny[0];若定义指针 int *p,另p=flizny,则指针里面存放的就是数组首元素的地址,即&flizeny[0]。
2、根据程序理解。
#include#define SIZE 4 int main(void) { int dates[SIZE]; int *ptin; int index; ptin=dates; for(index=0;index (1)、指针中存放着数组首元素的地址。由index为0时的输出结果可以看出,指针中存放了一个地址。
(2)、对一个指针加一的结果是对指针增加一个存储单元。由于指针指向数组,因此地址会增加到下一个元素的位置,而不是下一个字节。由于是int类型的数组,一个元素占四个字节,因此对指针加一就是加四个字节。
(3)可以用指针标识数组的每个元素,并得到每个元素的数值。 例如:dates+2==&date[2]; *(dates+2)==dates[2]; //可以看到前者与后者有相同的地址和相同的值。
三、指针、数组和函数。1、编写对数组进行操作的函数。
例如,要调用一个对数组进行操作的函数,sum(shuzu);其中shuzu是一个int型的地址,应把它赋值给一个指向int的指针,因此函数的声明为:int sum (int * ar),也可以写成 int sum(int ar[])。即由于数组名是首元素的地址,所以如果实际参数是一个数组名,则形式参数必须是与之相匹配的指针。
2、在函数体中指明数组长度的办法。
(1)、在函数体中写上固定长度的数组大小。
#define SIZE 10 int sum (int *ar) { int i; int total; for (i=0;i<10;i++) total+=ar[i]; return total; }(2)、把数组大小作为第二个参数传递给函数。
int sum(int *ar,int n) { int i; int total=0; for(i=0;i(3)、传递两个指针,一个指明起始地址,一个指明结束地址。
#define size 10 int main (void) { long answer; int marbles[10]; answer=sump(marbles,marbles+size); return 0; } int sump(int *start,int *end) { int total=0; while(start四、指针操作。 五、保护数组的内容---const的作用。
赋值 可以把一个地址赋给指针,用数组名或地址运算符进行赋值。 求值 运算符*可以取出指针指向地址中存储的数值。 取指针地址 用&运算符可以得到指针本身的地址。 将一个整数加给指针 这个整数会和指针所指类型的字节数相乘,所得的结果加到初始地址,所以ptr+4相当于&a[4]。 增加指针的值 用加法或者增量运算符来增加一个指针的值。对指向某数组元素的指针做增量运算,可以让指针指向该数组的下一个元素。 从指针中减去一个整数 这个整数会和指针所指类型的字节数相乘,所得的结果从初始地址减掉。例如:ptr3-2结果等同于&a[2],因为ptr3本来指向a[4]。 较小指针的值 指针减小一个值,会指向前一个元素。 求差值 可以求出两个指针间的差值。通常对分别指向同一个数组内的两个元素的指针求差值,以求出元素之间的距离。 比较 可以用一个指针减去另一个指针得到一个整数,也可以从一个指针中减去一个整数得到一个指针。 1、原因。
对于处理数组的函数,只能传递指针,但是由于处理数组的函数直接操作原始数据,所以它能够修改原始数据。若不想让函数修改数组的内容,可以在函数原型和定义的形式参量中使用关键字const。Const并不要求原始数组是固定不变的,只是说明函数在处理数组时,应该把数组当做是固定不变的。
2、const的使用。
(1)、int sum (const int ar[]); //函数把ar指向的数组作为包含常量数据的数组对待。
(2)、double rates[5]={1,2,3,4,5};
Const double *pd=rates;
//把pd声明为指向const double的指针,就不能用pc修改它指向的值了。但是由于rates并没有声明为常量,所以仍可以用rates来修改其数值。
3、规则。
将常量或者非常量的数据的地址赋给指向常量的指针是合法的,但是只有非常量数据的地址可以赋给普通指针。
4、const的其他用法。
(1)、用const声明并初始化指针。Double *const pc=rates;这样指针仍然可以修改数据,但是只能指向最初赋给它的地址。
(2)、可以使用两个const来创建指针,这个指针既不可以更改所指向的地址,也不可以修改所指向的数据。即:const double *const pc=rates;
六、指针和多维数组。
1、函数是通过指针来处理多维数组的。
利用以下数组为例进行分析:
int zippo[4][2];(1)、Zippo:数组名zippo也是数组首元素的地址,首元素本身又是包含两个int的数组,因此zippo也是包含两个int数组的地址。即:zippo=&zippo[0];
(2)、zippo[0]:因为zippo[0]是包含两个int的数组,因此zippo[0]的值就是其首元素的地址&zippo[0][0]。即:zippo[0]=&zippo[0][0];
(3)、Zippo和zippo[0]:简单地说,zippo是两个整数大小对象的地址,而zippo[0]是一个整数大小对象的地址,因为他们开始于同一个地址,因此zippo和zippo[0]具有相同的数值。对一个指针加一,会在原来的数值上加上一个对应类型大小的数值,因此zippo+1和zippo[0]+1的结果不同。
(4)、对一个指针取值,得到的是该指针所指向的对象的数值。因为zippo是地址的地址,需要两次取值才可以得到通常的值。
*zippo=zippo[0]; *zippo[0]=zippo[0][0]; zippo[0]=&zippo[0][0];
*zippo=&zippo[0][0]; **zipoo=*&zippo[0][0]; **zippo=zippo[0]0];
2、指向多维数组指针的声明。
声明二维数组的指针变量时,必须保证指针pz指向一个包含两个int值的数组,而不是单个的int值。正确的代码是:
Int (*pz)[2]; //pz是指向一个包含两个int值的数组
指针之间的赋值规则比数值类型的赋值更严格。例如,可以不需要进行类型转换就直接把一个int数值赋给一个double类型的变量。但对于指针来说,这样的赋值是不允许的。
3、函数和多维数组。
编写处理二维数组的函数时,一种方法是把处理一位数组的函数应用到二维数组的每一行上。函数调用多维数组的声明方式如下:
Int sum2(int ar[] [4],int rows);
表示ar指向由4个int值构成的数组,也就是16个字节长的对象,所以ar+1表示在这个地址上加上16个字节大小。一般的,声明N维数组指针时,除了最左边的方括号可以留空之外,其他的都需要填写数据。
Int sum4(int ar[][12][20][30],int rows);
因为首方括号表示这是一个指针,其他方括号描述的是所指向对象的数据类型。以上形式等效为:
Int sum4(int (*ar)[12][20][30],int rows);
七、变长数组。
C99引入变长数组,允许使用变量定义数组各维。但是,变长数组有一些限制,必须是自动存储类的,这意味着它们必须在函数内部或作为函数参量声明,而且声明时不可以进行初始化。且变长数组的大小在创建后是保持不变的。例如:
int qua=4; int reg=5; double sales[reg][qua];在使用时,变长数组可以声明为:
Int sum2d(innt rows, int cols, int ar[rows][cols]);变长数组和一般数组的区别在于数组定义时,普通数组的方括号中放的是数值或用const定义的常量;而变长数组的方括号中放的是变量。



