C語言指針與數組

C語言指針與數組程序員

數組的下標應該從0仍是1開始? 我提議的妥協方案是0.5,惋惜他們未予認真考慮便一口回絕    -- Stan Kelly-Bootle
 
1. 數組並不是指針
爲何不少人會認爲指針和數組始終應該能夠互換的呢? 由於對數組的引用老是能夠寫成對指針的引用,並且確實存在一種指針和數組的定義徹底相同的上下文環境,
不幸的是,這只是數組的一種極爲普通的用法,並不是所用狀況下都是如此。
 
2. 什麼是聲明,什麼是定義
C語言中對象必須有且只有一個定義,但它能夠有多個extern聲明.
定義:只能出如今一個地方, 肯定對象的類型並分配內存,用於建立新的對象,例如 int a[100]
聲明:能夠屢次出現,描述對象的類型,用於指代其餘地方定義的對象(例如在其餘文件裏) 例如 extern int a[100]
extern對象聲明告訴編譯器對象的類型和名字,對象的內存分配則在別處進行
 
3. 數組與指針的區別
出如今賦值左邊的符號被稱爲 左值, 出如今賦值右邊的符號被稱爲 右值。
編譯器爲每一個變量分配一個地址(左值),這個地址在編譯時可知,而且該變量在運行時一直保存於這個地址中。
存儲於變量中的值(右值)只有在運行時纔可知,若是須要用到變量中存儲的值,編譯器就發出指令從指定地址讀入變量並將它存於寄存器中。
例如: char a[9] = "abcdefgh";   c = a[i] 
假設編譯器符號表具備一個地址9980
運行時步驟1:取 i 的值,將它與 9980 相加 (基址加偏移量)
運行時步驟2:取地址 [9980+i] 的內容
 
例如:char* p;  c = *p;
假設編譯器符號表有一個符號p,它的地址爲4624
運行時步驟1:取地址 4624 的內容,假設是 1024
運行時步驟2:取地址1024的內容
 
例如:char* p = "abcdefgh"   c = p[i]
假設編譯器符號表有一個p,地址爲 4624
運行時步驟1:取地址4624的內容,假設是 1024
運行時步驟2:取得 i 的值,並將它與 1024 相加  (基址加偏移量)
運行時步驟3:取地址 [1024+i] 的內容
 
 
指針 數組
保存數組的地址    保存數據

間接訪問數據,首先取指針的內容,把它做爲地址,而後從這個地址提取數據。數組

若是指針有一個下標[i],就把指針的內容 加上i做爲地址,從中提取數據   數據結構

直接訪問數據 a[i]只是簡單的以a+i做爲地址取數據
一般用於動態數據結構                一般用於存儲數目固定且數據類型相同的元素
相關的函數爲 malloc free 隱式分配和刪除
一般指向匿名數據      自身即爲數據名
定義指針時,編譯器沒有爲指針所指向的對象分配空間,只是分配指針自己的空間
ANSI C中,初始化指針時所建立的字符串常量所定義爲 只讀。在有些編譯器中,字符串常量被存放在只容許讀取的文本段中,以防止它被修改
char* ptr = "hello world"    // 這種寫法是很是不推薦的,由於 ptr 所指對象是隻讀的,這將隱式的將 const 轉 non-const,任何對 ptr 的修改都會 coredump
const char* ptr = "hello world"   // 這種寫法明確表示 ptr 的const屬性,這時對 ptr 所指對象的修改都會 在編譯時報錯
char a[] = "hello world"              //這種寫法代表 數組中元素都是可修改的,可是 數組名是不可修改的左值,即數組首地址不能夠改變,是常量
 
4. 何時數組與指針相同
全部做爲函數參數的數組名能夠經過編譯器轉換爲指針
數組的聲明就是數組,指針的聲明就是指針,二者不能混淆
注意:若是定義一個數組,在其餘文件中對它extern聲明時也必須把它聲明爲數組,指針也是如此
 
在使用數組(在語句或表達式中引用)時,數組老是能夠寫成指針的形式
 
數組下標表達式老是能夠改寫成帶偏移量的指針表達式
 
何時數組和指針是相同的:
規則1:表達式中的數組名(與聲明不一樣)被編譯器看成一個指向該數組第一個元素的指針 (具體見 ANSI C標準 第6.2.2.1 節)
規則2:下標老是與指針的偏移量相同(具體見ANSI C標準 第6.3.2.1 節)
規則3:在函數參數的聲明中,數組名被編譯器看成指向該數組第一個元素的指針(具體見ANSI C標準 第6.7.1 節)
 
其實規則1和規則1合起來理解以下:對數組下標的引用老是寫成"一個指向數組的起始地址的指針加上偏移量"
對數組的引用如a[i]在編譯時老是被編譯器改寫成*(a+i)指針訪問的形式
 
"做爲函數參數的數組名"等同於指針
void func(int* arg);
void func(int arg[10]);
void func(int arg[]);
上述三種形式是徹底等同的
 
5. 爲何C語言把數組形參看成指針
把做爲形參的數組和指針等同起來是出於效率緣由的考慮
在C語言中,全部非數組形式的數據實參均以傳值形式(對實參作一份拷貝並傳遞給調用的函數,函數不能修改做爲實參的實際變量的值,而只能修改傳遞給它的那份拷貝)調用
C語言容許程序員把形參聲明爲數組(程序員打算傳遞給函數的東西)或者指針(函數實際所接收到的東西)
無論程序員實際所寫的是哪一種形式,函數並不自動知道指針所指數組共有多少個元素,因此必須有個約定,如數組以NULL結尾或者另外一個附加的參數表示數組的範圍
能夠經過向函數傳遞一個指向數組第一個元素的指針來訪問整個數組,但也可讓指針指向任何一個元素,這樣傳遞給函數的就是從該元素以後的數組片斷
相關文章
相關標籤/搜索