1. 程式人生 > >C語言之指針

C語言之指針

就是 for 答案 基本類型 %d alloc 動態分配 快速 style

指針

指針和指針變量的關系   指針就是地址,地址就是指針   地址就是內存單元的編號   指針變量是存放地址(內存單元的編號)的變量   指針和指針變量是兩個不同的概念   但要註意:通常我們會把指針變量簡稱為指針表,實際含義不一樣   指針的本質就是一個操作受限的非負整數   重要性:   表示一些復雜的數據結構   快速的傳遞數據 減少了內存的耗用【重點】   使函數返回一個以上的值【重點】   能直接訪問硬件   能夠方便的處理字符串   是理解面向對象語言中引用的基礎   定義:   地址:   內存單元的編號
  從0開始的非負整數   範圍:4G 【0---4G-1】   分類:     1.基本類型指針【重點】   附註:     *
的含義
  1.乘法   2.定義指針變量    int *p;//定義一個名字叫p的變量,int *表示p只能存放 int變量地址   3.指針運算符    該運算符放在已經定義好的指針變量的前面    如果p是一個已經定義好的指針變量   則*p表示以p的內容為地址的變量   如何通過被調函數修改主調函數普通變量的值   1.實參必須為該普通變量的地址   2.形參必須為指針變量   3.在被調函數中通過    *形參名 = ·····   的方式就可以修改主調函數相關變量的值     2.指針和數組   指針和一維數組   一維數組名:   一維數組名是個指針常量   它存放的是數組第一個元素的地址   下標和指針的關系   如果p是個指針變量,則   p[i]永遠等價於 *(p+i)   確定一個一維數組需要幾個參數【如果一個函數要接受一個一維數組,需要哪些條件】數組第一個元素的地址和數組長度
# include <stdio.h>

//
f函數可以輸出任何一個一維數組的內容 void f(int * pArr,int len) { int i; for(i = 0;i < len;++i) printf("%d",*(pArr + i)); /*(pArr + i)等價於 pArr[i] 也等價於 數組[i] printf("\n"); } int main(void) { int a[5] = {1,2,3,4,5}; int b[6] = {-1,-2,-3,4,5,-6}; int c[100] = {1,99,22,33}; f(a,5); //a是int *類型,需要數組第一個元素的地址和長度 f(b,6); f(c,100); return 0; }
# include <stdio.h>

//f函數可以輸出任何一個一維數組的內容 
void f(int * pArr,int len)
{
    pArr[3] = 88;
}
int main(void)
{
    int a[6] = {1,2,3,4,5,6};
    printf("%d\n",a[3]);
    f(a,6);
    printf("%d\n",a[3]);
    return 0; 
}
/*
4
88
*/
指針變量的運算 指針變量不能相加,不能相乘,也不能相除,只能相減 如果兩個指針變量指向的是同一塊連續空間中的不同存儲單元,則這兩個指針變量才可以相減
# include <stdio.h>


int main(void)
{
    int i = 5;
    int j = 10;
    int *p = &i;
    int *q = &j;
    int a[5];
    p = &a[1];
    q = &a[4];
    printf("p和q所指向的單元相隔%d個單元\n",q-p); 
    //p-q沒有實際意義 
    return 0; 
}
一個指針變量到底占幾個字節【非重點】 預備知識: sizeof(數據類型) 功能:返回值就是該數據類型所占的字節數 例子:sizeof(int) = 4 sizeof(char) = 1 sizeof(double) = 8 sizeof(變量名) 功能:返回值是該變量所占的字節數 假設p指向char類型變量(1個字節) 假設p指向char類型變量(4個字節) 假設p指向char類型變量(8個字節) p q r本身所占字節數是否一致? 答案:一致 總結:   1.一個指針變量,無論它所指向耳朵變量占幾個字節   該指針變量本身只占四個字節   2.一個變量的地址使用該變量首字節的地址來表示    指針和二維數組   3.指針和函數   4.指針和結構體   5.多級指針
//多級指針 
# include <stdio.h>

int main(void)
{
    int i = 10;
    int *p = &i;
    int **q = &p;
    int ***r = &q;
    
    /*
        *r = q->**r = *q = p->***r = **q = *p = i
    */
    
    //r = &p;  //因為r是int ***類型,r只能存放int **類型變量的地址
    printf("i = %d\n",***r);
     
    return 0;
}
//多級指針 
# include <stdio.h>

void f(int **q)  //*q就是p 
{
    
} 

void g()
{
    int i = 10;
    int *p = &i;
    f(&p);  //p是int *類型,&p是int ** 類型 
}
int main(void)
{
    g(); 
     
    return 0;
}
專題: 動態內存分配【重點難點】
傳統數組的缺點: 1.數組的長度必須事先指定,且只能是常整數,不能是變量 例子: int a[5]; //OK int len = 5;int a[len];//error 2.傳統形式定義的數組,該數組的內存程序員無法手動釋放 在一個函數運行期間,系統為該函數中的數組所分配的空間會一直存在,直到該函數運行完畢時,數組的空間才會被系統釋放 3.數組的長度不能在函數運行的過程中動態的擴充或縮小 數組的長度一旦定義,其長度就不能再更改 4.A函數定義的數組在A函數運行期間可以被其他函數使用,但A函數運行完畢之後,A函數中的數組無法再被其他函數使用 傳統方式定義的數組不能跨函數使用 為什麽需要動態分配內存 動態數組很好的解決了傳統數組的這4個缺點 傳統數組也叫靜態數組 動態內存分配舉例--動態數組的構造
/*
    malloc是memory(內存)  allocate(分配)的縮寫 
*/

# include <stdio.h>
# include <malloc.h>  //不能省 
int main(void)
{
    int i = 5;  //分配了4個字節  靜態分配
    int *p = (int *)malloc(4);//12行 
    /*
        1.要使用malloc函數,必須添加malloc.h這個頭文件
        2. mallo0c函數只有一個形參,並且形參是整型
        3.4表示請求系統為本程序分配4個字節
        4.malloc函數只能返回第一個字節的地址
        5. 12行分配了8個字節,
            p變量占4個字節,p指向的內存也占4個字節 
        6.p本身所占的內存是靜態分配的,p所指向的內存是動態分配的
         
    */ 
    *p = 5;//*p代表的就是一個int變量,
        //只不過*p這個整型變量的內存分配方式和11行的不同 
    
    free(p);  //free(p)表示把p所占的內存給釋放掉 
            //    p本身的內存是靜態的,不能由程序員手動釋放 
    printf("同誌們好!\n"); 
    return 0;
    
}
# include <stdio.h>
# include <malloc.h> 
int main(void)
{
    int len;
    int *pArr;
    int i;
    //動態的構造一維數組 
    printf("請輸入您要存放的元素的個數:");
    scanf("%d",&len);
    pArr = (int *)malloc(4 * len);
    //對一維數組進行操作 
    for(i = 0;i < len;++i) 
        scanf("%d",&pArr[i]);
        
    //對一維數組進行輸出
    printf("一維數組的內容是:\n");
    for(i = 0;i < len;++i)
        printf("%d\n",pArr[i]);
        
    free(pArr);  //釋放掉動態分配的數組 
    return 0;
}
靜態內存和動態內存的比較   靜態內存是由系統自動分配,由系統自動釋放   靜態內存是在棧分配的   動態內存是由程序員手動分配,手動釋放   動態內存是在堆分配的 跨函數使用內存的問題   靜態變量不能跨函數使用
# include <stdio.h>

void f(int **q)  //q也是個指針變量,
                //無論q是什麽類型的指針變量,都只占4個字節 
{
    int i = 5;
    //*q等價於p q和**q都不等價於p 
    //*q = i;  //error  因為*q = i;等價於p = i,這是錯誤的
    *q = &i;  //p = &i; p = *q; --> *q = &i;
}
int main(void)
{
    int *p;
    
    f(&p);
    //printf("%d\n",*p); 
     //本語句語法沒有問題,但邏輯有問題 ,它是靜態分配的
    return 0;
}

動態內存可以跨函數使用

# include <stdio.h>
# include <malloc.h> 
void f(int **q)
{
    *q = (intn *)malloc(sizeof(int));
        //sizeof(數據類型)  返回值是該數據類型所占的字節
    **q = 5;  //*p = 5;
}
int main(void)
{
    int *p;
    f(&p);
    printf("%d\n",*p);  //沒有錯誤,函數沒有終止 ,因為是動態分配的
    return 0;
}

C語言之指針