C语言指针(二)

C语言规定,一维数组名本身代表数组在内存中的首地址,即数组中第一个元素的地址。

指针与一维数组

1、一维数组元素的地址

对于一个数组元素a[i],其地址有以下三种表示方式。
(1)下标法
   &a[0]表示数组第一个元素的地址,&a[3]表示数组第四个元素的地址,&a[i]表示数组元素a[i]的地址。
(2)指针法
  这种方法要先定义指向数组元素的指针。

int a[10];
int *p;
p=a;

  此时,p的值为数组a的起始地址,即&a[0];则p+i表示元素a[i]的地址,即p+i等价于&a[i]。
若定义p=&a[k],则p指向a[k],则p+i表示元素a[k+i]的地址。
(3)地址法
  设有如下定义:
       int a[3],*p=a;
则数组a各元素的地址如下表 。

数组元素 下标法 指针法 地址法
a[0] &a[0] p a
a[1] &a[1] p+1 a+1
a[2] &a[2] P+2 a+2
2、一维数组元素的引用方法

与上述三种数组元素的地址表示法相对应,一维数组元素的引用也有三种方法。
(1)下标法
例:a[i[;
(2)指针法

int a[10];
int *p;
p=a;

则*(p+i)将得到下标为i的元素的值,即 *(p+i)与a[i]等价。
(3)地址法
因为a+i 表示数组元素a[i]的地址,所以*(a+i)表示数组元素a[i]的值

在使用指针变量时,要注意:
  (1)指针变量可以自增、自减,而数组名不可以自增、自减。数组名是数组的首地址,它的值在程序运行期间固定不变,是常量。
  (2)要注意指针变量的当前值。
  (3)使用指针或地址法访问数组元素时,要注意防止下标越界

指针与二维数组

1、二维数组元素的地址

(1)下标法
  &a[i][j]表示a[i][j]的地址。

(2)指针法
  设执行语句p=&a[0][0],这是p指向数组a的第一个元素a[0][0]。利用指针和整数的加法即可表示a[i][j]的地址为p+i*10+j,其中的10是数组a的第二维长度,即数组每一行的元素的个数。
若p=&a[m][k],则a[i][j]的地址表示为p+(i-m)*10+(j-k)。(能这样计算的根据是数组元素在内存中是按行连续存放的)

(3)地址法
  a[i][j]的地址表示法与一维数组相同,即a[i]+j就是a[i][j]的地址,因此&a[i][j]等价于a[i]+j

  也可用二维数组名a来表示地址。把a看作是由若干个“行元素”构成的数组,每个“行元素”是一个一维数组,则可视a[0],a[1],a[2]为a的三个“行元素”。它们的地址则是a的各行的首地址,用符号&a[0]、&a[1]、&a[2]来表示,也可用a、a+1、a+2表示,即&a[0]等价于a,&a[1]等价于a+1,&a[2]等价于a+2。则可用*(a+i)表示a[i],于是 a[i][j]的地址表示为*(a+i)+j,或者称*(a+i)+j指向a[i][j]

设有如下定义:
       int a[2][3],*p=a;

行元素 元素 下标法 地址法 地址法 指针法
a[0] a[0][0] &a[0][0] a[0]+0 *(a+0)+0 p+0*3+0
a[0] a[0][1] &a[0][1] a[0]+1 *(a+0)+1 p+0*3+1
a[1] a[1][0] &a[1][0] a[1]+0 *(a+1)+0 p+1*3+0
a[1] a[1][1] &a[1][1] a[1]+1 *(a+1)+1 p+1*3+1
2、二维数组元素的引用

与二维数组元素的地址表示方法相对应,引用二维数组也有三种方法。

设有如下定义:

int a[2][3],*p;
p=&a[0][0];

则有
a[i][j]=*(p+i*3+j)=*(*(a+i)+j);(等价)

3、指向由m个元素组成的一维数组的指针变量

定义指向一维数组的指针的一般形式为:
      数组类型 (*指针变量名)[n];
例如:int (*p)[4];定义了一个指向一维数组的指针变量p,该一维数组由4个元素组成,这些元素时整型数据。由于p不是指向数组的基本元素,而是指向一个一维数组,即指向二维数组中的一行,指向一维数组的指针可用于处理二维数组,通过初始化或赋值语句使指针指向二维数组的行。因此,p++运算使指针p指向下一行,向后跳过4个int数据所占的字节。

例:用指向数组的指针存取二维数组的元素。

/*编译环境,Dev-C++*/
#include<stdio.h>
int main(){
    int i,j;
    int a[4][4],(*p)[4];
    p=a;
    for(i=0;i<4;i++)
       for(j=0;j<4;j++)
           scanf("%d",*(p+i)+j);
    printf("\n");
    for(i=0;i<4;i++)
       {
        for(j=0;j<4;j++)
           printf("%3d",*(*(p+i)+j));
        printf("\n");
       }
}

指针数组

  由指向同一数据类型数据的指针为元素组成的数组称为指针数组。定义指针数组的一般形式为:
       数据类型 *数组名[数组长度];
  指针数组中的每个元素都是指向所定义数据类型的指针变量。常用在字符串处理中。字符串指针数组可以通过初始化获得一批常量字符串的首地址。
  例如:char *str[3]={“one”,”programming”,”ok”};
  上例定义了一个具有三个元素的数组,每一个元素都是指向字符串型数据的指针,指针中存储它所指向的字符串的首地址。该定义语句等价于如下的语句:

char *str[3];
str[0]=”one”;
str[1]=”programming”;
str[2]=”ok”;

例:用字符串初始化指向char类型的指针数组,并输出这些串。

/*编译环境,Dev-C++*/
#include<stdio.h>
int main(){
    const char *str[5]={"one","two","three","four","five"};
    int i;
    for(i=0;i<5;i++)
        printf("%s  ",str[i]);
} 

           各种指针类型的定义形式及其含义

定义形式 含义
int *p; p为指向整型数据的指针变量
int (*p)[n]; p为指向含有n个元素的一维数组的指针变量
int *p[n]; p为指针数组,含有n个元素,每个元素可指向一个整型数据
int **p; p为一个指针变量,可指向一个整型数据的指针变量

综合应用
  使用指针,把输入的任意5个字符串,按字典顺序(从小到大)输出。

#include<stdio.h>
#include<string.h> 
int main(){
    char str[5][40],ss[40];
    char (*p)[40],(*q)[40],(*pos)[40];
    for(p=str;p<str+5;p++)
           gets((char *)p);    /*输入5个字符串*/
    for(p=str;p<str+4;p++){    /*排序*/
        for(q=(pos=p)+1;q<str+5;q++)
           if(strcmp((char *)q,(char *)pos)<0) pos=q;

        if(pos!=p){        /*交换*/ 
            strcpy(ss,(char *)p);
            strcpy((char *)p,(char *)pos);
            strcpy((char *)p,ss);
        }
    }

    for(p=str;p<str+5;p++)
        puts((char *)p);    /*输出*/ 
}

猜你喜欢

转载自blog.csdn.net/yangmolulu/article/details/79533271