C/C++——C語言數組名與指針


版權聲明:原創文章,轉載請注明出處。

 


1. 一維數組名與指針

 

對於一維數組來說,數組名就是指向該數組首地址的指針,對於:

int array[10];

array就是該數組的首地址,如果我們想定義一個指向該數組的指針,我們可以用如下定義:

int *p;

然后令:

p = array;

那么指針p就指向了數組array的首地址,此時我們可以向操作array一樣操作p:

#include <stdio.h>

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

    for(int i=0;i<10;i++){
        printf("%d ",p[i]);
    }
    printf("\n");

    for(int i=0;i<10;i++){
        printf("%d ",*(array+i));
    }
    printf("\n");

    for(int i=0;i<10;i++){
        printf("%d ",*(p+i));
    }
    printf("\n");
    return 0;
}

結果如下:

 


2. 多維數組名與指針

 

但是如果我們定義一個多維數組,如:

int arrays[2][2];

數組名arrays是數組元素的首地址,如果我們還用上面的那種定義:

int *p;
p = arrays;

這樣p就指向了該多維數組的首地址,由於多維數組其實是數組的數組,所以多維數組的首地址就是一個地位的數組的首地址,即arrays[0],它是一個有2個元素的數組。因此我們可以將一維數組名賦值給int*型的指針,

#include <stdio.h>

int main(){
    int arrays[2][2] = {1,2,3,4};
    int *p = arrays;
    for(int i=0;i<4;i++){
        printf("%d ",p[i]);
    }
    printf("\n");
    return 0;
}

結果如下:

可以發現,編譯時發生警告:

我們之所以可以通過p來遍歷arrays中所有元素,是因為,數組本質上是按行優先存儲的。

我們可以通過兩次解引用獲取到數組中的某一個元素的值,有下式成立:

**arrays == *&arrays[0][0] == arrays[0][0]

 如:

#include <stdio.h>

int main(){
    int arrays[2][2] = {1,2,3,4};
    int *p = arrays;
    printf("%d == %d == %d\n",**arrays,*&arrays[0][0],arrays[0][0]);
    return 0;
}

結果:

 

對於多維數組我們可以定義一個指向多維數組的指針:

int (*p)[2];
p = arrays;

這個括號是一定要加的,因為[]的優先級比較高(?)。

比較 int *p[2] 和 int (*p)[2] :

  •  int *p[2] 表示p是一個有2個元素的數組,數組中的每一個元素表示一個指向int型變量的指針;
  •  int (*p)[2] 表示p是一個指針,它指向一個數組,數組中的每個元素指向一個有2個元素的數組。

 

因此我們知道 int (*p)[2] 與arrays有同樣的數組結構,p就是arrays的一個別名,我們可以通過p來實現任何arrays能實現的操作:

#include <stdio.h>

int main(){
    int arrays[2][3] = {1,2,3,4,5,6};
    int (*p)[3] = arrays;
    for(int i=0;i<2;i++){
        for(int j=0;j<3;j++){
            printf("%d ",p[i][j]);
        }
        printf("\n");
    }
    return 0;
}

結果如下:

 


3. 數組名和指針的區別

 

數組名和指針之間,經常會交替使用這兩個變量,例如把一個指針當成數組來使用,或者是把數組名賦值給指針,通過指針來訪問數組成員變量。

但是,數組名和指針畢竟是定義不同的變量,它們之間也有一定的區別和聯系。

理解數組名和指針的區別和聯系有助於我們正確使用C語言,即什么情況下該使用數組名,什么情況下該使用指針。

 

區別1:

數組名和指針取地址后的值不一樣: 

  • 數組名取地址得到的是數組名所指元素的地址。 
  • 對指針取地址得到的是指針變量自身的地址。

 

1)對於數組名:

#include <stdio.h>

int main(){
    int array[6] = {1,2,3,4,5,6};
    printf("array     = 0x%x\n",array);
    printf("&array[0] = 0x%x\n",&array[0]);
    printf("&array    = 0x%x\n",&array);
    return 0;
}

輸出結果如下:

 我們已經知道,數組名即數組首元素的地址,因此array和&array[0]的值一樣,但是令我們驚奇的是,數組名的地址&array和和數組首元素的地址&array[0]也一樣。 

2)對於指針:

#include <stdio.h>

int main(){
    int array[6] = {1,2,3,4,5,6};
    int *p = array;
    printf("array     = 0x%x\n",array);
    printf("&array[0] = 0x%x\n",&array[0]);
    printf("&array    = 0x%x\n",&array);

    printf("\np         = 0x%x\n",p);
    printf("&p        = 0x%x\n",&p);
    return 0;
}

結果如下:

可以發現指針的值和指針所在的地址是不同的。

 

區別2: 

數組名是指針常量,指針是指針變量。

  • 數組是固定大小的,數組一經定義,那么數組名就是一個指向數組首元素類型的常量指針,也就是說數組名是不允許更改的;
  • 但是我們知道除非定義指針常量,否則指針變量是可以再賦值的。 

 

區別3: 
當對數組名使用sizeof時,得到的是數組所有元素所占的字節數,對指針sizeof得到的是指針類型的字節數。 

#include <stdio.h>

int main(){
    int array[6] = {1,2,3,4,5,6};
    int *p = array;
    printf("sizeof array    = %d   bytes\n",sizeof(array));
    printf("sizeof pointer  = %d    bytes\n",sizeof(p));
    return 0;
}

輸出如下:

 

區別4:

 對數組名取&和對指針取&的意義不同。 

 

#include <stdio.h>

int main(){
    int array[6] = {1,2,3,4,5,6};
    int *p = array;
    printf("&array      = 0x%x\n",&array);
    printf("&array + 1  = 0x%x\n\n",&array + 1);
    printf("&p          = 0x%x\n",&p);
    printf("&p + 1      = 0x%x\n",&p + 1);
    return 0;
}

輸出如下:

上圖可以看到對array取地址后加一,增大了24個字節,恰好是數組的大小;而對指針p取地址后加一,只增大了8個字節,恰好是一個指針類型所占的字節數。

  


4. 總結

 

  1. 數組名代表了一個指向數組首元素的指針常量,一經定義,不可更改;指針是指針變量,定義之后仍可更改,其類型在定義時確定。
  2. 當出現 sizeof 和 & 操作符時,數組名不再當成指向一個元素的指針常量來使用,而指針仍當成指向一個元素的指針變量來使用。
  3. 對於使用指針和數組下標的選擇: 
    1. 系統在使用數組下標對數組成員變量進行訪問時,開銷比較大,指針的訪問效率是遠遠大於數組名的訪問效率的;
    2. 但是只有在指針正確訪問時,使用指針才比下標法更有效率; 
    3. 下標法更加容易理解,在可讀性方面,也更加的具有優勢。

 


 

參考資料:

  1. https://blog.csdn.net/findgeneralgirl/article/details/78501734
  2. https://blog.csdn.net/dream_follower/article/details/80356754


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM