C语言指针与数组笔记2

8.3通过指针引用数组
8.3.1数组元素的指针

一个变量有地址,一个数组包含若干个元素,每个数组元素都在内存中占用储存单元,它们都有相对应的地址。指针变量可以指向变量,也可以指向数组元素。数组元素的指针就是数组元素的地址。
可以用一个指针变量指向数组元素,例如:

int a[10] = {1,3,4,6,7,9};//定义一个整型数组
int * p;//定义p为指向整型变量的指针变量
p = &a[0];//把a[0]的地址赋值给了指针变量
//p = a等价于p = &a[0]

????注意:程序中的数组名不代表整个数组,只代表数组首元素的地址。

定义指针变量初始化:

int * p = a;//或者int * p =&a[0]

它的作用是将数组a的首元素地址赋值给指针变量p。

8.3.1在引用数组时的指针的运算
在一定条件下允许对指针进行加和减的运算。在指针指向数组元素时,可以对指针进行以下运算:

加一个整数(用+或+=),如p+1;
减一个整数(用-或-=),如p-1;
自加运算,如p++, ++p;
自减运算,如p–,--p。
两个指针相减,如p1-p2(只有p1和p2都指向同一个数组中的元素时才有意义)
分别说明如下:

(1)如果指针变量p已指向数组中的一个元素,则p+1指向同一个数组中的下一个元素,p-1指向同一个数组中的上一个元素。执行p+1时并不是将p的值(地址)简单地加1,而是加上一个数组元素所占用的字节数。例如,数组元素是float型,每个元素占用4个字节,则p+1意味着使p的值加4个字节,以使它指向下一个元素。

(2)如果p的初值为&a[0],则p+i和a+i就是数组元素a[i]的地址,或者说它们指向a数组序号为i的元素。

(3)(p+i)和(a+i)是p+i或a+i所指向的数组元素,即a[i]。例如,(p+5)或(a+5)就是a[5],即这三者等价。

(4)如果指针变量p1和p2都指向同一数组,如执行p2-p1,结果是p2-p1的值(两个地址之差)除以单个数组元素的长度。表示p1和p2所指元素的相对距离,两个地址不能相加,如p1+p2是无实际意义的。

8.3.3通过指针引用数组元素
(1)下标法,如a[i]类型。
(2)指针法,如*(a+i)或*(p+i)。其中a是数组名,p是指向数组元素的指针变量。
例如:用指针变量p来访问数组元素。

#include<stdio.h>
int main()
{
  int arry[] = {56,67,98,45,23};
  int i;
  int * ptr_arry = arry;//赋值完毕就可以使用指针访问数组元素了
  for(i = 0;i < 5;i++)
  {
    printf("第%d个元素的值是%d\t地址是%p\n",i,*ptr_arry,ptr_arry);
    ptr_arry ++;
  }
}

C语言指针与数组笔记2

⭐插入一个小提示:*(p++)和 *(++p)的作用是不相同的。
*(p++)先取 *p值,再使p加1。
(++p)先使p加1,再取p值。

8.3.4用数组名作函数参数

在用数组名作为函数实参时,既然实际上相应的形参是指针变量,为什么还允许使用形参数组的形式呢?

这是因为在C语言中用下标法和指针法都可以访问一个数组(如果有一个数组a,则a[i]和*(a+i)无条件等价),用下

标法表示比较直观,便于理解,因此许多人愿意用数组名作形参,以便与实参数组相对应。从应用的角度看,用户可以认为

有一个形参数组,它从实参数组那里得到起始地址,因此形参数组和实参数组共占同一段内存单元,在调用函数期间,如果

改变了形参数组的值,也就改变了实参数组的值。

注意:实参数组名代表的是一个固定的地址,或者说是一个指针常量,但形参数组名并不是一个固定的地址,而是按指针变量处理。
例题:将数组a中n个整数按相反顺序存放
这时,我们可以用指针变量作形参。

#include<stdio.h>
int main()
   {
      void inv(int *x,int n);//inv函数申明
      int i,arry[10],*p = arry;//指针变量P指向arry[0]
      printf("please input the original number:\n");
      for(i = 0;i < 10;i++)
      scanf("%d",p);//输入arry数组的元素,也可以用printf("%d",arry[i])
      printf("\n");
      p = arry;//指针变量重新指向arry[0]
      inv(p,10);//调用inv函数,实参P是指针变量
      printf("the arry has inverted:\n");
      for(p = arry;p < arry + 10;p++)
      {
        printf("%d",*p);
        printf("\n");
        return 0;
      }
    }
void inv(int *x,int n)   //定义inv函数,形参x是指针变量
{
    int * p,m,temp,* i,* j;
    m = (n - 1)/2;
    j = x + n - 1;p = x + m;
    for(i = x;i <= p;i++,j--)
    {
      temp = *i;
      *i = *j;
      *j = temp;
      return ;
    }
}

运行结果
C语言指针与数组笔记2

8.3.5通过指针引用多维数组

int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}};

表示形式 含义 地址
a 二维数组名,指向一维数组a[0],即0行首地址 2000
a[0], * (a+0), * a 0行0列元素地址 2000
a+1,&a[1] 1行首地址 2016
a[1], *(a+1) 1行0列元素a[1][0]的地址 2016
a[1]+2, * (a+1)+2, &a[1][2] 1行2列元素a[1][2]的地址 2024
*(a[1]+2), ((a+1)+2), a[1][2] 1行2列元素a[1][2]的值 元素值为13

如果用一个指针变量指示一维数组,应该是这样定义的:
int (*p) [4];
p表示为指向由4个整型元素组成的一维数组。

指向多维数组元素的指针变量
例:有一个34的二维数组,要求用指向指针元素的指针变量输出二维数组各元素的值。
解题思路:二维数组的各元素都是整型,它相当于整型变量。所有可以用int
型指针变量指向它。可以用一个指向整型元素的指针变量,依次指向各元素。

#include<stdio.h>
int main()
   {
     int a[3][4] = {1,3,5,7,9,11,13,15,17,19,21,23};
     int * i;//定义一个指针变量i
     for(i = a[0];i < a[0] + 12;i++)
     {
        if((i -a[0])%4 == 0)
        printf("\n");
        printf("%4d",*i);
     }
    printf("\n");
    return 0;

}

运行结果
C语言指针与数组笔记2

8.5通过指针引用字符串

用指针方式与用字符数组方式操作字符串的区别:

(1)存储方式不同。字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串首个字符的地址),决不是将字符串放到字符指针变量中。

(2)赋值方式不同。

对字符数组只能对各个元素赋值,不能用以下办法对字符数组赋值。

char str[20];

str="Good luck!"; 

而对字符指针变量,可以采用下面方法赋值:

char *str;

str="Good luck!";

赋给str的不是字符,而是字符串第一个元素的地址。

(3)输入方式不同。

对字符数组可用如下方式赋值:

char str[20];

scanf("%s",str);  //ok

但对字符指针变量则不建议用此方式,因为会发生指针的异常指向,正确做法为:

char *str,a[20];

str=a;  //使指针有明确的指向

scanf("%s",str);

(4)字符指针变量的值是可以改变的,而字符数组名的值是不可以改变的。

例1:#include <stdio.h>

void main()

{

char *str="Good luck!";

puts(str);

str+=5;  //ok

puts(str);

}

例2:

#include <stdio.h>

void main()

{

char str[20]="Good luck!";

puts(str);

str+=5;  //error!

puts(str);

}

????指针的指针的指针

指向指针的指针也就是“二级指针”。

定义方式如下:类型说明 **指针变量名

即定义一个二级指针变量,类型说明是它指向的指针变量所指向的变量的数据类型。它所指向的指针变量称为一级指针变量。

赋值形式为:二级指针变量=&一级指针变量;

这类似于张三有李四的地址,而王五有张三的地址,这样王五通过张三找到李四。这样张三是一级指针,而王五是二级指针。

例如:

#include <stdio.h>

void  main()

{char *name[]={ "Follow me","BASIC","Great Wall″,

"FORTRAN","Computer design"};

char **p;int i;

for(i=0;i<5;i++)

{ p=name+i; printf(″%s\n″,*p);}

}