程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 指針資料整理

指針資料整理

編輯:C++入門知識

這些天筆試經常碰到指針的題目,故做了一個整理。

 

指針在應用中的各種類型:
(1)  int *ip;  //(char* cp,float* fp,double* dp)  一級指針變量
(2)  int **ip;  //(char** cp,float** fp,double** dp) 二級指針變量
(3)  const int* ip;  //常量指針
(4)  int* const ip;  //指針常量
(5)  const int* const icp; //常量指針常量
(6)  int *ip[10];   //指針數組
(7)  int (*ip)[10]; //數組指針
(8)  int *f(int a); //char* copy(char* s1, char* s2)  指針函數
(9)  int (*gp)(int);  //函數指針
(10) int (*gp[10])(int); //函數指針的數組

下面針對這11中情況作一一解說
(1)  int *ip;  //(char* cp,float* fp,double* dp)  一級指針變量
一級指針是我們接觸最多,也是最簡單的指針。
#include <iostream>
using namespace std;

int main(void)
{
    char *p = "hello world";
    int i = 0;
    while(p[i] != '\0')
        cout << p[i++];
    cout << '\n';
   
    int *ip, iq;
    iq = 5;
    ip = &iq;
}
上面程序體現了二個問題:1)指針的增減運算 2)定義指針一個*只能修飾一個指針
    指針的增減是以該類型的實體大小為單位的(但對指針作乘除是沒有意義的)
        對char指針加 1 實際增加了1個字節
         對float指針加 1 實際增加了4個字節
        對int指針加 1 實際增加了4個字節
   定義指針一個*只能修飾一個指針
        程序中的 ip是一個指針,而iq是一個整數變量

  在很多c/c++程序,指針跟數組進行替換使用,這樣以使得我們覺得指針跟數值是等價,但是數組跟指針還是有很大區別的,請看下面的例子。
#include <iostream>
using namespace std;

void fun(char a[100])
{
    cout << sizeof(a) << '\n';  //4
}

int main(void)
{
    char a[] = "hello world";
    a[0] = 'Y';
    char *p = "welcome to c++";
//    p[0] = 'X'; //編譯器不能發現該錯誤,但是運行時出錯
    cout << sizeof(a) << '\n';  //12
    cout << sizeof(p) << '\n';  //4
    fun(a);   
}

    看了上面的例子之後,我們來說說數組跟指針的區別:
     數組要麼在靜態存儲區被創建(如全局數組),要麼在棧上被創建。數組名對應著(而不是指向)一塊內存,其地址與容量在生命期內保持不變,只有數組的內容可以改變。
      指針可以隨時指向任意類型的內存塊,它的特征是“可變”,所以我們常用指針來操作動態內存。指針遠比數組靈活,但也更危險。
      字符數組 a 的容量是 12 個字符,其內容為 hello world\0。a 的內容可以改變,如 a[0]= ‘Y’。指針 p 指向常量字符串“welcome to c++”,(位於靜態存儲區,內容為 welcome to c++\0) ,
     常量字符串的內容是不可以被修改的。從語法上看,編譯器並不覺得語句 p[0]= ‘X’有什麼不妥,但是該語句企圖修改常量字符串的內容而導致運行錯誤,
     所以我們經常把char *p = "welcome to c++" 寫成 const char *p = "welcome to c++",這樣就能夠使得 p[0] = 'X'語句在編譯的時候就報錯。
     sizeof(a)的大小是12(注意別忘了\0) sizeof(p)是一個指針的大小,當把數組作為函數參數進行傳遞時,數組自動退化為指針。

指針參數如何傳遞內存的?
#include <iostream>
#include <string.h>
using namespace std;

char* getStr1()
{
    char a[] = "hello world";
    return a;
}

char* getStr2()
{
    char *a = new char[12];
    strcpy(a, "hello world");
    return a;
}

char* getStr3()
{
    char *a = "hello world";
    return a;
}

void getStr4(char *p, int num)
{
    p = new char[num];
    strcpy(p, "hello world");
}

void getStr5(char **p,int num)
{
    *p = new char[num];
    strcpy(*p, "hello world");
}
int main(void)
{
    cout << "getStr1 " << getStr1() << '\n';
   
    char *str2 = NULL;
    str2 = getStr2();
    cout << "getStr2 " << str2 << '\n';
    str2[0] = 'X';
    cout << "getStr2 " << str2 << '\n';
    delete [] str2;
    char *str3 = NULL;
    str3 = getStr3();
    cout << "getStr3 " << str3 << '\n';
//    str3[0] = 'X';  //編譯通過,但運行出錯
   
    char *str4 = NULL;
    int num = 50;
    getStr4(str4, num);
    cout << "getStr4 " << (str4 == NULL?"NULL": str4) << '\n';
   
    char *str5 = NULL;
    getStr5(&str5, num);
    cout << "getStr5 " << str5 << '\n';
}

getStr1()輸出的是亂碼,因為在getStr1()裡return的是棧內存,所以當退出函數之後,char a[]也隨著被清除了。
getStr2()能夠正確運行。
getStr3()雖然能夠正確運行,但是不管在什麼地方返回都是常量數據
getStr4()運行結束後,str4仍然還是NULL,因為char *p參數在getStr4()函數運行結束後隨著也被清除了
getStr5()能夠正確運行。

(2)  int **ip;  //(char** cp,float** fp,double** dp) 二級指針變量
    二級指針變量與一級指針變量的關系,跟二維數組與一維數組的關系有些類似,在這就不多說了


(3)  const int* ip;  //常量指針
(4)  int* const ip;  //指針常量
(5)  const int* const icp; //常量指針常量
    這3個有一些相似性,看如下例子。
#include <iostream>
using namespace std;

int main(void)
{
        const int a = 10;
        int b = 5;
        int c = 13;
        const int *ip = &a;
        int* const cp = &b;
        const int* const icp = &c;

        *ip = 30; //錯誤,常量指針不能修改指向的常量,*ip只能做右值
        ip = &c; //正確,指針本身能夠改變
        *cp = 50; //正確,指針常量,指針所指向的值能夠修改
        cp = &c; //錯誤,指針常量本身不能夠改變
        *icp = 50;//錯誤,常量指針常量不能修改指向的常量
        icp = &c; //錯誤,常量指針常量不能夠改變指針本身
}

(6)  int *ip[10];   //指針數組
(7)  int (*ip)[10]; //數組指針
    指針數組:顧名思義,就是說的首先是一個數組吧,然後數組的元素是指針而已
    數組指針:指向一個數組的指針
#include <iostream>
using namespace std;

int main()
{
        int a = 5, b = 1, c = 10;
        int *p1 = &a, *p2 = &b, *p3 = &c;
        int *p[3] = {p1, p2, p3}; //指針數組,數組中的每個元素都是一個指針
        for(int i = 0; i < 3; i++)
                cout << *p[i] << '\n';

        int (*ap)[3];       //數組指針
        int arr[4][3] = {{1,2},{2,3},{3}};
        ap = arr;
        for(int i = 0; i < 4; i++)
        {
                for(int j = 0; j < sizeof(ap[i])/sizeof(int); j++)
                        cout << ap[i][j] << " ";
                cout << '\n';
        }
}

(8)  int *f(int a); //char* copy(char* s1, char* s2)  指針函數
    指針函數是指函數返回值是一個指針類型
    如我們在c語言中經常使用strcpy就是這樣一個函數
    char* strcpy(char* Dest, const char* Src)
    {   
        assert(Dest != NULL &&Src !=NULL);
        char* tmp = Dest;
        while((*Dest++ = *Src++) != '\0');
        return tmp;
    }
    看到這函數,我們可能會覺得為什麼要有一個返回值呢?不是把Src的內容都已經復制到Dest中了麼,這個主要是為了完成了鏈式運算,為了是strcpy函數能夠作右值。

(9)  int (*gp)(int);  //函數指針
(10) int (*gp[10])(int); //函數指針的數組
#include <iostream>
using namespace std;

void fun1(){ cout << "good" << '\n';}
void fun2(){ cout << "better" << '\n';}
void fun3(){ cout << "best" << '\n';}


int main()
{
        void (*gp)() = fun1; //函數指針
        gp();

        void (*gpa[3])();//函數指針數組
        gpa[0] = fun1;
        gpa[1] = fun2;
        gpa[2] = fun3;
        for(int i = 0; i < 3; i++)
                gpa[i]();
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved