1. 程式人生 > >指標和陣列的定義與宣告

指標和陣列的定義與宣告

導語

在這裡我們做種強調的是在兩個檔案中,定義為陣列宣告為指標和定義為指宣告為陣列的這輛中情況。那麼我們就需要兩個原始檔test.c和main.c。

定義為陣列,宣告為指標

test.c

char arr[] = "abcdef";

main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>

extern char *arr;   //宣告

int main()
{
    printf("%s\n", arr);  
    system("pause"
); return 0; }

就會出現以下的錯誤:
這裡寫圖片描述
就會出現,讀取位置發生訪問衝突

  • 首先我們需要知道的是定義和宣告使用的是同一塊空間,我們在test.c中定義為陣列,在main.c中使用,不管宣告為陣列還是指標都是用的是這一塊空間。
    這裡將宣告的arr當為指標取出來的是四個位元組的值,然後在列印字串時,就會將這四個位元組的值作為一個地址去尋找,我們可以先來看看程式碼呈現。
    這裡寫圖片描述
    我們會發現“64636261”不是dcba的ASSCII碼嗎?所以我們就知道了它為何地址訪問出錯。看下圖:
    這裡寫圖片描述
    這裡指標去訪問了四個位元組的空間,然後取出了dcba,將dcba當做地址碼去取出字元,造成地址訪問出錯。
    那我們如何在定義為陣列、宣告為指標的情況下,取出陣列中所存的字串?

  • 要取出字串,就必須知道首元素’a’的地址,上述的描述,不就讓我們知道了arr中存放的就是64636261相當於dcba,我們對arr取地址就相當於取到了abcd的地址,我們在對這個地址強制轉換為char*型別,不就取到了一個位元組’a’的地址。字串知道了首元素地址,列印就很方便啦!
    main.c

#include <stdio.h>

extern char *arr;

int main()
{
    //printf("%s\n", arr);
    printf("%s\n", (char*)&arr);
    system("pause");
    return
0; }

這裡寫圖片描述

定義為指標,宣告為陣列

test.c

char *p = "abcdef";

main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdlib.h>
#include <stdio.h>

extern char arr[];  //這裡只是說他是一個數組,不需要填寫陣列個數

int main()
{
    printf("%s\n", p);
    system("pause");
    return 0;
}

執行之後就會發現,呀!我的程式執行出來是隨機值,不對呀,我明明將它存放進去了。

  • 首先我們就得清楚這個數組裡面存放的是什麼?
  • 定義為指標,然後指向了字串”abcdef”,這裡指標裡面就存的是字串首元素的地址
  • 宣告為陣列,定義為指標,大小隻有四個位元組,所以陣列的大小也只有四個位元組
  • 指標中存放的是字串首元素的地址,陣列中存放的是字串首元素的地址,所以打印出來就是亂碼了。
  • 圖解如下圖所示:
    這裡寫圖片描述

那我們如何在定義為指標、宣告為陣列的情況下,取出指標中所指向的字串?

  • 我們要找到字串,就要將指標所存放的四個位元組一次取出來,因為字元陣列一次只能讀一個位元組,所以,我們需要把它強轉為int*
  • 取出後,我們需要知道它裡面的內容,就必須把它解引用,取出四個位元組的地址,(int )p
  • 最後,我們要找到’a’的地址,就必須強轉為char*,才能取出’a’的地址。
    main.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdlib.h>
#include <stdio.h>

extern char p[];    //這裡只是說他是一個數組,不需要填寫陣列個數

int main()
{
    printf("%s\n", (char*)*(int*)p);
    system("pause");
    return 0;
}

這裡寫圖片描述
總結:
1. 定義和宣告使用的是同一塊空間
2. 指標大小是4個位元組,陣列大小不一定
3. 指標和陣列不一樣