8.C語言指針初步認識

C語言指針初步認識

==============

指針初步

==============

指針初步

            1.數據的存儲
                1》數據在內存中是如何存儲的
                2》數據存儲的地址和大小
            3.指針的定義和使用
                1》如何定義指針
                2》如何使用指針
            4.指針指向數組,p++的含義
                1》指針指向數組的含義
                2》理解p++
            5.泛指針、空指針、野指針
            6.const關鍵字

一、認識指針

地址:內存每個字節都有一個數字的編號,稱為地址。
指針:指針是一個變量,用來裝地址。
//指針是地址變量。地址是指針的常量。

int * p;

//創建了一個指針的變量
//指針是p,不是*p. 類型 int *

int a;
//一個變量是內存中的空間,a占4個字節,a的地址是a第一個字節的地址。

p=&a;

//&a表達式的值,是a的地址,即a第一個字節的地址

printf(“%ld %ld %ld\n”,sizeof(p),sizeof(int *),sizeof(*p));

printf(“%p\n”,p);
printf(“%lx\n”,p);

//當一個指針p,裝了變量a的地址,稱為p指向a。

int a;
int *p = &a;
char b;
char * q=&b;

問:int *指針多少字節,char * 指針又是多少字節?
32位系統地址都是4字節,64位系統地址是8字節。指針無論指向什么類型的變量,大小和地址相同。

二、認識*p

int a=5;
int * p=&a;
*p=6;
//對p取*,意思是,找到地址為p的值的字節,取4字節,得到一個空間,就是a。

*&a=8;
printf(“%d\n”,a);

p:找到(尋址)地址為p的值的字節,取p個字節,得到一個內存空間,其實就是p指向的變量空間。

*&a<——->a

練習:
1》聲明整型變量a,存儲數字5,用相應指針指向a,通過指針將a修改成6.

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        int a = 5;
        int b=5;
        //在內存中開辟了一個4字節空間,這個空間的名稱是a,存儲了一個5的常量
        int * p = &a;
        //指針p中存放了a的地址,我們稱為p指向了a    p——》a
        p = &b;
        * p = 6;
        //*p,找到p指向的變量的第一個字節的地址,并取指向變量類型的字節數,形成一塊空間,這個空間就是變量 b
        //*p     *p ==  *&a    p== &a   *p==a
        printf("%d\n",b);
        //
        //p是指針,它存放了a的地址,a有4個字節,即有4個地址,尋到指針p只存放a的第一個字節的地址。
        printf("%lu,%lu\n",sizeof(p),sizeof(int *));
        
    }
    return 0;
}

三、為什么使用指針?

int a =5;
int b=6;
swap(a,b);
swap2(&a,&b);
printf(“a5:%d  b6:%d\n”,a,b);


void swap(int a,int b)
{
    int t=a;
    a=b;
    b=t;
}

void swap2(int *p,int *q)
{
    int t =* p;
    *p =*q;
    *q =t;
}

指針就是為了跨棧訪問,訪問不再當前棧里的數據。

C/C++

一個由C/C++編譯的程序占用的內存分為以下幾個部分

1、棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數名,局部變量的名等。其操作方式類似于數據結構中的棧。

2、堆區(heap)— 由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收。注意它與數據結構中的堆是兩回事,分配方式倒是類似于鏈表

3、靜態區(static)—全局變量和局部靜態變量的存儲是放在一塊的。程序結束后由系統釋放。

4、文字常量區—常量字符串就是放在這里的,程序結束后由系統釋放 。

5、程序代碼區— 存放函數體二進制代碼

如果想,封裝一個函數,修改變量的值,形參必須是指向這個變量的指針,實參是這個變量的地址。

練習:
1》編寫函數,交換兩個變量。
2》編寫函數,求三個變量的最大值,求完之后,將三個變量清0.
3》編寫函數,修改一個變量,將變量的值,改為現有值的三次方。

四、指針和數組

1.指針加1
指針加1,加一個*p的字節數,加一個p指向變量的字節數。

int a;
int * p= &a;

printf(“%p\n”,p);
printf(“%p\n”,p+1);


int a[5]={1,2,3,4,5};
//用一個指向int的指針,指向這個數組的第一個元素。
int * p=&a[0];

*(p+1)=8;
printf(“%d\n”,a[1]);

2.數組名是數組的首元素地址
計算機并不知道數組有多長,只知道數組的首元素地址。

3.數組的傳參
//數組傳參后會蛻化成指針。

int a[5]={1,2,3,4,5};
//數組傳參,傳入數組的名字,也就是a[0]的地址。
//數組傳參,用指向第一個元素的指針來接收。
printArray(a,5);

void printfArray(int *p,int n)
{   //只要傳參正確,在main函數中怎樣使用數組,在本函數中怎樣使用數組。
    for(int i=0;i<n;i++){
        printf(“%d “,p[i]);

}

[注]數組傳參,傳入數組首元素地址(如同傳入數組每個元素的地址),用指向數組元素的指針來接收。
使用指向數組首元素的指針,和使用數組本身是一樣的。
數組傳參,都是傳入元素的地址,所以能夠在函數中修改數組的元素。

數組名是首元素地址常量
指針是變量,可以裝首元素的地址。

練習:

1》編寫函數,將任意長整型數組,逆序。

五、泛型指針和空指針

泛型指針:void * p;可以存儲任何變量的地址,沒有類型的限制,也可以和任何指針進行彼此賦值。

如:int *p;
    void *q=p;
    p=q;
//泛型指針不能進行加減,不能取*。無法取*q的字節數。

空指針:如果一個指針不初始化,只能認為指針指向不能預測的地方,稱為野指針。如果使用了野指針,會產生不能預知的錯誤。因此,應將不能及時初始化的指針暫時賦成NULL,當明確了指向對象時,再去指向那個對象。如果發生在指向對象前就訪問了,地崩潰。

int *p;
*p=5;


int *p=NULL;

//為了防止野指針錯誤不明顯,如果一個指針創建時,沒有現成的變量來初始化。將p初始化為NULL(空指針),NULL代表0x00。計算機不會分配0x00這個地址給任何字節。百分百崩潰。

六、const關鍵字

const int a=5;

//const修飾變量a,使a不能被修改

int b,c;
const int * p=&b;   //int const *p=&b;
//const 修飾指針
//const在*前,稱為*前const,所以修飾的是*p而不是p。
//*p不能改,p可以改。
p=&c;
//p指向誰,不能通過p修改誰。
c=5;
//可以改c,只是不能通過*p來修改c


int * const q=&b;
//*后const,修飾q,q不能改,*q可以改。

int a[5]={1,2,3,4,5};
printArray(a,5);



//可以遍歷打印數組,但不能改數組元素的值
void printArray(const int * p,int n)
{
    *p=6;   //不能改
}


//*后const幾乎沒有應用,只是C面試很容易考。

練習:

1》編寫函數,求任意長整型數組的平均數,返回。
2》編寫函數,求任意長整型數組中第二大的數。

指針案列代碼

指針

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        int a = 5;
        int b=5;
        //在內存中開辟了一個4字節空間,這個空間的名稱是a,存儲了一個5的常量
        int * p = &a;
        //指針p中存放了a的地址,我們稱為p指向了a    p——》a
        p = &b;
        * p = 6;
        //*p,找到p指向的變量的第一個字節的地址,并取指向變量類型的字節數,形成一塊空間,這個空間就是變量 b
        //*p     *p ==  *&a    p== &a   *p==a
        printf("%d\n",b);
        //
        //p是指針,它存放了a的地址,a有4個字節,即有4個地址,尋到指針p只存放a的第一個字節的地址。
        printf("%lu,%lu\n",sizeof(p),sizeof(int *));
        
    }
    return 0;
}

指針的作用

#import <Foundation/Foundation.h>
void swap(int a,int b);
void mySwap(int * p,int * q);
//1》編寫函數,交換兩個變量。
//2》編寫函數,求三個變量的最大值,求完之后,將三個變量清0.
void myMax(int * p,int * q,int * k);
//3》編寫函數,修改一個變量,將變量的值,改為現有值的三次方。
void myPow(int *p);
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
//        int a=5,b=6;
//        printf("a=%d\tb=%d\n",a,b);
//        swap(a, b);
//        printf("a=%d\tb=%d\n",a,b);
//        mySwap(&a, &b);
//        printf("a=%d\tb=%d\n",a,b);
//        int a,b,c;
//        printf("請輸入三個整數:");
//        scanf("%d%d%d",&a,&b,&c);
//        myMax(&a, &b, &c);
//        printf("a=%d b=%d c=%d\n",a,b,c);
        int a;
        printf("請輸入一個整數:");
        scanf("%d",&a);
        myPow(&a);
        printf("%d\n",a);
    }
    return 0;
}
void swap(int a,int b){
    int t=a;
    a=b;
    b=t;
}
void mySwap(int * p,int * q){
    int t = *p;
    *p=*q;
    *q=t;
}
void myMax(int * p,int * q,int * k){
    int max;
    if (*p>*q) {
        max=*p;
    }else{
        max= *q;
    }
    if (max<*k) {
        max=*k;
    }
    printf("最大值是:%d\n",max);
    *p=*q=*k=0;
}
void myPow(int *p){
    *p*=*p**p;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 指針是C語言中廣泛使用的一種數據類型。 運用指針編程是C語言最主要的風格之一。利用指針變量可以表示各種數據結構; ...
    朱森閱讀 3,470評論 3 44
  • 第十章 指針 1. 地址指針的基本概念: 在計算機中,所有的數據都是存放在存儲器中的。一般把存儲器中的一個字節稱為...
    堅持到底v2閱讀 1,085評論 2 3
  • C語言是面向過程的,而C++是面向對象的 C和C++的區別: C是一個結構化語言,它的重點在于算法和數據結構。C程...
    小辰帶你看世界閱讀 963評論 0 6
  • 那是一個漫長到分不清開始和結束的夢境啊 那是一條川流不息的冷清街道 那是一汪渾濁到看不清前世和今生的湖水啊 那是一...
    毛小偉_6080閱讀 188評論 0 0
  • 在1957年的十月,美國有很多值得憂慮的事情:蘇聯入侵、電視、炸彈威脅等,尤其是在四日這一天,蘇聯成功地將第一顆人...
    十言九不語閱讀 469評論 0 0