天天看點

再議 C 語言中的指針與數組(4)再議 C 語言中的指針與數組(4)

再議 C 語言中的指針與數組(4)

一 概述

前面的文章中,回顧了 C 語言中的指針,對指針有了一個比較初步的了解。在本文中,結合數組,再次對指針進行回顧。

二 數組與指針

在 C 語言中,指向數組的指針是比較常見的,也是非常友善和适用的。

2.1 指向數組的指針

# include<stdio.h>

int main(int argc,char *argv[]){
  int a[10] = {1,2,3,4,6,5,7,8,9,0};
  int *p;
  // p = a;
  p = &a[0];
  for (int i = 0; i < 10; i++){
    printf("%d\t",*p);
    p++;
  }
  return 0;
}
// 1       2       3       4       6       5       7       8       9       0           

本例中,指針變量 p 指向了數組 a[10],并示範了通過指針周遊數組的正常方法。 我們可以直接通過數組名直接将指針指向該數組的第一個元素,“p = a;” 和 “p = &a[10];”這兩行代碼在本質上是等價的。需要注意的是:通過這種方式使指針指向整個數組,數組名前面不能再使用運算符 &。 若指針指向數組的某一進制素,運算符 & 不能省略。

2.2 指向複合常量的指針

# include<stdio.h>

int main(int argc,char *argv[]){
  int *p = (int []){1,2,3,4,6,5,7,8,9,0};
  for (int i = 0; i < 10; i++){
    printf("%d\t",*p);
    p++;
  }
  return 0;
}
//1       2       3       4       6       5       7       8       9       0           

本例聲明并初始化了一個沒有名稱的數組。 通過這種方式,我們不需要先聲明一個數組,然後再用指針指向數組的第一個元素。 在某些場景中,這個特性使用起來比較友善。 這是 C99 的一個特性。 另外, 在本例的 for 循環體,聲明并初始化了 i, 這也是 C99 的一個特性,需要注意一下。

可以聲明匿名數組的長度。

# include<stdio.h>

int main(int argc,char *argv[]){
  int *p = (int [10]){1,2,3,4,6,5,7,8,9,0};
  for (int i = 0; i < 10; i++){
    printf("%d\t",*p);
    p++;
  }
  return 0;
}           

2.3 通過指針對數組進行操作

通過指針也可以很友善、高效地對數組進行操作,請看以下例子:

# include<stdio.h>
# define N 10

int main(int argc,char *argv[]){
  int a[N];
  int *p;
  for (p = a; p < a + N; p++){
    printf("Please input a[%d]:",p - a);
    scanf("%d",p);
  }
    for (p = a; p < a + N; p++){
    printf("a[%d] = %d;\t ", p - a, *p);
  }
  printf("\n");
  return 0;
}
/*
Please input a[0]:1
Please input a[1]:2
Please input a[2]:3
Please input a[3]:4
Please input a[4]:5
Please input a[5]:66
Please input a[6]:7
Please input a[7]:7
Please input a[8]:8
Please input a[9]:9
a[0] = 1;        a[1] = 2;       a[2] = 3;       a[3] = 4;       a[4] = 5;       a[5] = 66;      a[6] = 7;       a[7] = 7;       a[8] = 8;       a[9] = 9;
*/           

這個例子展示了通過操作指針對數組進行指派,并通過指針的移動完成對數組的周遊。例子中使用了兩個指針相減的方式确定了數組下标。使用指針操作對數組進行指派或周遊的過程中,在操作開始之前需要将指針複位,指向數組的第一個元素。這個操作必不可少,否則将出錯。

2.4 指針與數組在函數定義中的使用

在函數定義時,數組可以使用指針或顯示聲明來定義形式參數。

# include<stdio.h>

int main(int argc,char *argv[]){
  unsigned int array[] = {3,5,6,7,1,2,0}, len;
  int find_max(unsigned int [], int n);
  len = sizeof array / sizeof array[0];
  printf("%d\n",find_max(array,len));
  return 0;
}

int find_max(unsigned int a[], int n){
  int max = 0;
  for (int i = 0; i < n; i++){
    if ( a[i] > max)
       max = a[i];
  }
  return max;
}
// 7           
# include<stdio.h>

int main(int argc,char *argv[]){
  unsigned int array[] = {3,5,6,7,1,2,0}, len;
  int find_max(unsigned int [], int n);
// int find_max(unsigned int *, int n);
  len = sizeof array / sizeof array[0];
  printf("%d\n",find_max(array,len));
  return 0;
}

int find_max(unsigned int *a, int n){
  int max = 0;
  for (int i = 0; i < n; i++){
    if ( a[i] > max)
       max = a[i];
  }
  return max;
}
// 7           

在以上2段代碼中,寫法不一樣,但執行效果卻一緻。事實上數組作為形參時,是以指針進行傳遞的。也就是說,對于形參而言,聲明為數組與聲明為指針是一樣的,但是對于變量來說,聲明為數組與聲明為指針是不一樣的。指定長度的數組會導緻編譯器預留指定資料類型長度的空間,申明為指針會導緻編譯器為指針變量配置設定空間。

2.5 多元數組與指針

使用指針周遊多元數組:

# include<stdio.h>

int main(int argc,char *argv[]){
  int *p, array[2][3] = {{12,43,11},{10,56,89}};
  for (p = &array[0][0]; p <= &array[1][2]; p++)
    printf("array[%d][%d]: %d\n",(p - &array[0][0])/3, (p - &array[0][0])%3, *p);
  return 0;
}
/*
array[0][0]: 12
array[0][1]: 43
array[0][2]: 11
array[1][0]: 10
array[1][1]: 56
array[1][2]: 89
*/           

以上代碼等價于:

# include<stdio.h>

int main(int argc,char *argv[]){
  int *p, array[2][3] = {{12,43,11},{10,56,89}};
  for (p = array[0]; p <= &array[1][2]; p++)
    printf("array[%d][%d]: %d\n",(p - &array[0][0])/3, (p - &array[0][0])%3, *p);
  return 0;
}           

對比以上兩端代碼,乍一看,并沒有什麼差異!舉着個例子的重點在第四行的 “p = &array0” 和 “p = array[0]”。通過這兩行代碼,不難看出:二維數組中,指針 p 不是指向 array0 的指針,而是指向 array[0] 的指針。

多元數組是不能以數組名直接作為指針指向的對象,需要稍微做一些調整才能使用數組名作為指針。在 C 語言中,多元數組實際上就是以一維數組來進行處理的。結合上面的例子,C 語言把 array 當作一維數組來進行處理,而這個一維數組的美一個元素又是一個一維數組。由此,可以推廣到多元數組。

那麼,在多元數組内是否可以直接以數組名為作為指針呢?請看以下例子:

# include<stdio.h>
# define ROWS 2
# define COLS 3

int main(int argc,char *argv[]){
  int *p, array[ROWS][COLS] = {{12,43,11},{10,56,89}};
    for (p = *array; p < *array + (ROWS * COLS); p++)
      printf("array[%d][%d]: %d\n",(p - *array) / COLS, (p - *array) % COLS, *p);
  return 0;
}
/*
array[0][0]: 12
array[0][1]: 43
array[0][2]: 11
array[1][0]: 10
array[1][1]: 56
array[1][2]: 89
*/           

在這一代碼片段中,将指針變量 p 指向一個指針類型的數組。也就是說,指針變量 p 指向了一個數組,這個數組的全部元素均為指針。簡而言之,指針變量 p 是指向指針數組的指針。

三 總結

3.1 在 C 語言中,指針與數組關系密切,既有聯系又有差別。在實際的使用過程中要特别謹慎。

3.2 指針是 C 語言中的精華。作為一名 C 語言學習者,指針雖然比較坑,但是這個是無法逃避的,必須花大量的時間與精力去學習與了解。

3.3 指針常常會與數組發生關聯,對指針的了解必須透徹。

3.4 鑒于筆者水準,文中可能存在若幹謬誤,希望大家能幫忙指出,謝謝!

繼續閱讀