把《c++ primer》讀薄(4-2 c和c++的數組 和 指針初探)

督促讀書,總結精華,提煉筆記,拋磚引玉,有不合適的地方,歡迎留言指正。ios

問題一、咱們知道,將一個數組賦給另外一個數組,就是將一個數組的元素逐個賦值給另外一數組的對應元素,相應的,將一個vector 賦給另外一個vector,也是將一個vector 的元素逐個賦值給另外一vector 的對應元素:c++

    //將一個vector 賦值給另外一vector,使用迭代器訪問vector 中的元素
    vector<int> ivec(10, 20);
    vector<int> ivec1;
    
    for (vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); iter++) {
        ivec1.push_back(*iter);
    }

問題二、編寫程序判斷兩個數組是否相等,而後編寫一段相似的程序比較兩個vector。程序員

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 using std::string;
 5 using std::vector;
 6 using std::cin;
 7 using std::cout;
 8 using std::endl;
 9 
10 int main(void)
11 {
12     const int size_array = 5;
13     int arr1[size_array];
14     int arr2[size_array];
15     
16     cout << "輸入數組 arr1的元素,個數爲" << size_array << endl;
17     
18     for (int i = 0; i != size_array; i++) {
19         cin >> arr1[i];
20     }
21     
22     cout << "輸入數組 arr2的元素,個數爲" << size_array << endl;
23     
24     for (int i = 0; i != size_array; i++) {
25         cin >> arr2[i];
26     }
27     
28     //比較大小
29     for (int i = 0; i != size_array; i++) {
30         if (arr2[i] != arr1[i]) {
31             cout << "數組 arr1和2不相等!" << endl;
32             
33             return 0;
34         }
35     }
36     
37     cout << "數組 arr1和2相等!" << endl;
38     
39     return 0;
40 }

輸入數組 arr1的元素,個數爲5數組

1安全

2函數

3spa

4指針

5code

輸入數組 arr2的元素,個數爲5對象

1

2

3

4

5

數組 arr12相等!

Program ended with exit code: 0

or

輸入數組 arr1的元素,個數爲5

1

2

3

1

2

輸入數組 arr2的元素,個數爲5

1

2

3

4

5

數組 arr12不相等!

Program ended with exit code: 0

vector 容器比較大小,這注意,vector 容器和數組的不一樣之處!vector 容器動態變大小,能夠求的長度,能夠在尾部直接插入元素。

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 using std::string;
 5 using std::vector;
 6 using std::cin;
 7 using std::cout;
 8 using std::endl;
 9 
10 int main(void)
11 {
12     vector<string> svec1;
13     vector<string> svec2;
14     string str;
15     
16     cout << "輸入字符串,做爲容器 vector1 的元素,輸入 off 結束!" << endl;
17     cin >> str;
18     
19     while(str != "off")
20     {
21         svec1.push_back(str);
22         cin >> str;
23     }
24     
25     cout << "輸入字符串,做爲容器 vector2 的元素,輸入 off 結束!" << endl;
26     cin >> str;
27     
28     while(str != "off")
29     {
30         svec2.push_back(str);
31         cin >> str;
32     }
33     //比較長短,對於 vector 容器,須要注意下,容器是可變長的
34     if(svec1.size() != svec2.size())
35     {
36         cout << "兩個容器不等!" << endl;
37     }
38     //要麼長度相等,要麼不等,若是相等,則假如都爲0
39     else if (svec2.size() == 0)
40     {
41         cout << "兩個容器相等!" << endl;
42     }
43     //若是相等且不爲0,則比較元素
44     else
45     {
46         vector<string>::iterator iter1;
47         vector<string>::iterator iter2;
48         iter1 = svec1.begin();
49         iter2 = svec2.begin();
50         
51         while(*iter1 == *iter2 && iter1 != svec1.end() && iter2 != svec2.end())
52         {
53             iter2++;
54             iter1++;
55         }
56         //若是元素都相等的話,必然是兩個迭代器都同時指向了末位的後一位
57         if(iter1 == svec1.end())
58         {
59             cout << "容器相等!" << endl;
60         }
61         else{
62             cout << "容器不等!" << endl;
63         }
64     }
65     
66     return 0;
67 }

問題三、指針的理解,以及和迭代器的區別

指針是一種複合數據類型,指向某種類型的對象,能夠做爲數組的迭代器。指針用來指向單個的對象,能夠經過指針間接訪問對象,而迭代器只能訪問容器內的元素!

指針通俗的理解:

指針就是一個變量(通常說是一個數據對象),只不過變量的內容是地址。好比int類型變量內容是整數,而指針變量內容是地址,僅此而已。沒什麼神祕的!

p = &q;//p是一個變量,&q是一個常量存儲了q的地址,賦值給p,咱們說p指向了q。
val = *p;// *叫作間接運算符(也叫取值運算符),能夠獲取p地址中存放的數值,val獲得了p指向的值。

由於p存放的是這塊內存的地址,而不是這塊內存裏的數值,故要想獲得這塊內存裏的數值,就要用取值運算符*p,找到這塊內存的地址p,而後取出這塊地址裏的數值來。兩句等價於:

val = q;

再次強調,現代 c++程序,應該避免使用指針還要數組!很容易出錯,使得程序員不能把精力集中到業務上。現代 c++程序採用 vector 類型和迭代器替代通常狀況下的數組的操做,使用標準庫 string 類型取代 c 風格的字符串。

指針的聲明

    //取值(間接)運算符*表面了變量是指針變量
    //類型標識符說明了被指向變量的類型
    int *pi;//pi是一個指向int類型的指針,可是*pi是int類型
    char *pc;//pc是一個指向char類型的指針,*pc是char類型的。
pc的值是一個地址,而pc所指向的值(*pc)是char類型,那麼指針pc自己也是一種類型,叫作指向char的指針類型。

注意:指針的值是一個地址,通常用無符號整數表示,可是指針絕對不是一個整數類型。不要和處理整型相混淆。只要記住:指針是一種新的數據類型!

指針做爲函數參數,指針能夠實現函數間的通訊

 1 void change(int *x, int *y);//指針變量做爲參數
 2 int main()
 3 {
 4     int x = 5, y = 6;
 5     printf("原來的:x=%d, y=%d", x, y);
 6     change(&x, &y);//把主調函數裏x和y的地址傳遞到函數做爲參數,這樣修改了函數的變量,由於傳遞的是主調函數的變量的地址而不是主調函數裏的數值。這樣在被調函數裏操做(交換)的就是主調函數的變量內容了。
 7     printf("\n改變的:x=%d, y=%d", x, y);
 8     system("pause");
 9     return 0;
10 }
11 void change(int *x, int *y)
12 {//等價於變量交換,x和y都是地址,必須加*,就是自己存儲的數值了
13     int temp;
14     temp = *x;//把指針x(地址)指向的內容(main函數裏的變量x值)賦值給temp(俗稱temp指向了x)
15     *x = *y;//地址y的內容賦值給地址x的內容
16     *y = temp;//把指針x指向的內容賦值給了地址y裏的內容
17 }

函數參數傳遞的是x和y的地址,而不是x和y自己的內容,能夠改變調用函數裏變量的值。

注意:指針的使用以前,必須初始化,不然極其容易致使程序奔潰(尤爲是接引用操做),發生運行時錯誤!能夠初始化爲一個對象地址,或者 NULL(0),或者另外一個指針。可是直接給指針賦值整型變量是非法的!如:

    int a;
    int zero = 0;
    const int b = 0;
    //int *ptr = a;error
    //int *ptr = zero;//error,int 類型的變量不能賦值給指針,即便=0也不行
    int *ptr = b;//ok,能夠被常量0賦值,等價 NULL
    int *p = 0;//ok,直接爲0是能夠的,或者爲 NULL,這裏最規範的寫法是 NULL,不要使用0作空指針賦值,不規範!
    int *pi = NULL;

NULL是 c++從 c 繼承而來的,定義在 cstdlib 頭文件裏,值就是0,屬於預處理器變量,編譯時被0替換。且注意:預處理器變量沒有在 std 命名空間裏定義!不用加 std::NULL。

指針只能被同類型的變量地址或者指針初始化,以及賦值!

必須保證指針的類型匹配,初始化或者賦值的時候尤爲注意這個問題。

int i; 
double* dp = &i;

非法。dp 爲指向double 型對象的指針,不能用int 型對象i 的地址進行初始化。

c 和 c++裏特殊的指針類型 void *

能夠保存任何類型對象的地址,意思是說:該指針和某一個地址值相關,可是不清楚存儲在此地址上的對象的類型!

支持的操做:和另外一個指針比較,給函數傳遞 void* 類型指針或者返回 void* 類型的指針,給另外一個 void *類型的指針賦值。可是絕對不能使用 void* 類型的指針操縱它所指向的對象。

int i = 42;
void *p = &i;
long *lp = &i;

具備void*類型的指針能夠保存任意類型對象的地址,所以p 的初始化是合法的;而指向long 型對象的指針不能用int 型對象的地址來初始化,所以lp的初始化不合法。

問題四、兩種指針聲明的形式,解釋寧願使用第一種形式的緣由:

int *ip; // good practice

int* ip; // legal but misleading

第一種形式強調了ip 是一個指針,這種形式在閱讀時不易引發誤解,尤爲是當一個語句中同時定義了多個變量時。

問題五、爲何指針使用以前必須初始化

由於,在C/C++語言中,沒法檢測指針是否未被初始化,也沒法區分一個地址是有效地址,仍是由指針所分配的存儲空間中存放的不肯定值的二進制位造成的地址。故建議在使用指針以前,必須初始化指針,更好的作法是,初始化所有的變量。避免運行時出錯

問題六、指針和引用的比較

他們都能間接的取訪問另外一值,可是有區別:

一、引用老是指向某個對象,定義引用必須初始化!不然報錯!

二、給引用賦值,修改的是引用所關聯的對象,而不是讓引用和新的對象取關聯!引用初始化以後,始終指向這個特定的對象(不會再改變)。

    int ival1 = 1024;
    int ival2 = 2048;
    int *pi = &ival1;
    int *pi2 = &ival2;
    pi = pi2;

pi指向的 ival1對象不會改變,賦值修改的 pi 指針的值,使得指向另外一個不一樣的對象。但原來的對象不會改變

    int ival1 = 1024;
    int ival2 = 2048;
    int &pi = ival1;
    int &pi2 = ival2;
    pi = pi2;

賦值改變了 pi 引用的值—ival 1對象,而沒有修改引用自己!和指針不同!由於引用就是之前變量的別名!是同樣的東西!而指針是兩個東西。

總結:

使用引用(reference)和指針(pointer)均可間接訪問另外一個值,但它們之間存在兩個重要區別:

(1)引用老是指向某個肯定對象(事實上,引用就是該對象的別名),定義引用時沒有進行初始化會出現編譯錯誤;

(2) 賦值行爲上存在差別:給引用賦值修改的是該引用所關聯的對象的值,而不是使該引用與另外一個對象關聯。引用一經初始化,就始終指向同一個特定對象。給指針賦值修改的是指針對象自己,也就是使該指針指向另外一對象,指針在不一樣時刻可指向不一樣的對象(只要保證類型匹配)。

問題七、二級指針

c 語言裏,在函數內部形參指針動態申請了內存,那麼常常用到二級指針取傳遞。c++裏所有使用引用,安全高效!

所謂二級指針:就是指向指針的指針,指針自己也是可用指針指向的內存對象。

    int ival = 1024;
    int *pi = &ival;//pi 指針是一級指針,指向了 int 變量 ival 的內存地址
    int **ppi = &pi;//ppi 二級指針,把指向 ival 對象的指針的地址存放在 ppi 指針變量裏
    
    //解引用操做
    int *pi2 = *ppi;//解引用二級指針到一級指針,至關於pi2指針指向了 ival 對象的地址
    //兩次解引用才能真正訪問到對象自己
    int a = **ppi;

問題八、下列程序段實現什麼功能?

int i = 42, j = 1024;

int *p1 = &i, *p2 = &j;

*p2 = *p1 * * p2;

*p1 *= *p1;

該程序段使得i 被賦值爲42 的平方,j 被賦值爲42 與1024 的乘積。

問題九、二維數組

一個背景:分析5年的銷售數據,一年12個月,通常用月爲最小單位。那麼須要定義一個60長度的數組麼?顯然不合適。其實把每一年的數據單獨放在一塊兒最好了,能夠設置5個數組,每組12。不過也顯得繁瑣,好比處理10年,20年等,就不爽了。數組的數組,也就是二維數組能夠處理這種問題。

    double d[5][12];//定義一個數組的數組(二維數組),5個由12個浮點數組成的數組的數組
    //d[5] 是一個包含5個元素的一維數組,而其中5個元素的每個元素又是一個包含12個浮點數的數組
    //也就是說,數組d的每一個元素類型都是double[12]
    //首元素就是d[0][0],是double類型的
    //二維數組:有5行,每行包含12列。改變第二個下標是沿着行移動,改變第一個下標是沿着列垂直移動
    //數組是順序存儲的 如圖所示:5行,12列的二維數組

二維數組的初始化

int i[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

數組的數組進行初始化,外層的每一維數組初始化列表都用花括號括起來,並且中間也是用逗號隔開.對於一維數組的初始化問題,一樣適用於二維數組,好比第一行列表裏元素少了,那麼剩餘的元素自動初始化爲0,若是多了,一樣報錯,並且一行和一行獨立的,不影響之後的賦值。也能夠省略內部的括號,只要最外面那層的括號,可是要保證正確.

    int i[3][3] = {
        1, 2, 3,
        4, 5, 6,
        7, 8, 9
    };//不建議,由於多了容易出錯

注意:多維數組初始化的兩種方式效果不一樣

第一種就是內部初始化列表也帶括號的

int i[2][3] = {
        {4, 5},
        {7, 8}
    }; //很明顯,初始化列表不夠數組大小

還有一種內部不帶花括號

還有一種內部不帶花括號
    int i[2][3] = {
        4, 5,
        7, 8
    }; //很明顯,初始化列表不夠數組大小

等價於: int i[2][3] = {4, 5, 7, 8}; //注意區分!

多維(二維以上)數組

    double d[2][3][4];//三維數組的聲明形式,更多維也同樣
    //能夠這樣理解:
    //一維數組是一行的元素列表排列,能夠當作一條線
    //二維數組裏有多行元素列表排列,能夠當作一個面
    //三維數組是多個二維的面一層層的摞起來,一個立方體。

一般處理一維數組用一層循環,二維數組用兩層循環,多維用多層循環,以此類推,他們的初始化是同樣的,大同小異。不過多維的用的不是太多。

問題十、數組和指針的聯繫初探

指針能夠直接操做內存地址,而計算機的硬件指令很大程度依賴地址,故程序員能夠用相似於計算機底層的表達方式來控制程序,更加高效的工做,而且指針能夠有效處理數組,數組標記其實是一種變相使用指針的形式。數組名就是這個數組首元素的地址

    float flt[3] = {1, 2, 3}; //
    flt == &flt[0];//數組名是該數組首元素的地址,注意這裏是等號不是賦值號。由於二者都是常量,程序運行的過程裏不變
    flt = &flt[0]; //error,這是錯誤的, error C2106: 「=」: 左操做數必須爲左值

問題十一、指針的加法運算

指針的加法

    //指針加法,SIZE值是3
    short dates[SIZE];
    short *pi;
    short index;
    double bills[SIZE];
    double *pf;
    //pi = dates;//把數組地址(首元素的地址)賦值給指針變量
    pi = &dates[0];
    pf = bills;//有兩種方式
    printf("%18s %8s\n", "short", "double");
    for (index = 0; index < SIZE; index++)
    {//pi存放dates數組的首地址,pf存放bills數組的首地址
        printf("指針 + %d : %p %p\n", index, pi + index, pf + index);
        //打印觀測指針加一操做以後的變化
    }

指針 + 0:這一行打印的是數組的首地址,之後每行都是地址加一打印,16進制。

發現:0018fad4+1=0018fad6麼,其餘也是相似。這說明對指針+1操做等價於加上了指針所指向的對象的字節的大小,指針每加一就是意味着加上對象大小的字節一次。因此咱們聲明指針變量必定要說明指針指向的對象的數據類型,由於計算機須要知道存儲對象用的字節數。

以上程序,pi是指向short類型的指針,pf是指向double類型的指針,指針的數值就是它指向的對象的地址,地址的內部表示方式硬件決定,不少計算機都是以字節編址的,說明計算機對每一個內存字節進行編號,對於多字節的數據類型,好比double(8字節)對象的地址通常就是其首字節地址。而對指針使用間接運算符*,就嫩獲得該指針指向的對象的具體的數值(再也不是該對象的地址了)。

    //下面的值是等價的
    dates == &dates[0];
    dates + 2 == &dates[2];
    *(dates + 2) ==dates[2];

這些都說明c和 c++在描述數組的時候,藉助了指針,他們有密切聯繫

  int i[SIZE];
  *(i + SIZE);//意思是尋址到內存中的i(數組首元素地址),而後繼續找SIZE個單位,找到該地址再取出裏面存放的數值

注意:間接運算符*的優先級高於+

    *i + 10;//意思是整型數組i的首元素的值(一個整數)和整數10相加的和
    *(i + 10);//意思是i數組的第11個元素的值

以上說明,咱們能夠用指針來標記數組,一樣用數組也能夠訪問指針.兩種方式各有用處,好比在數組做爲函數參數的時候,這關係就很重要.

問題十二、函數裏的數組和指針

求一個整型數組的所有元素和的函數

分析:若是函數只需接收一個整型的數組名和這個數組的大小就能計算出和,那麼函數參數應該是兩個,一個是大小size,一個是接收數組名稱,又知道數組名就是數組首元素的地址(數組首地址),那麼必然用到指針參數來接受。

#include <stdlib.h>
#include <stdio.h>
int sum(int *i, int n);
int main()
{
    int in[5] = {1, 2, 3, 4, 5};
    printf("%d", sum(in, 5));//打印15
    system("pause");
    return 0;
}
int sum(int *ii, int num)
{
    int index;
    int total = 0;
    for (index = 0; index < num; index++)
    {
        total += ii[index]; //ii[index]和*(ii + index)等價的
    }
    return total;
}

注意:第一個參數把數組首地址和數組的類型傳遞給了函數,第二個參數把數組大小傳遞給函數。由於實際參數是一個數組名,故形式參數必須是匹配的指針。

當且僅當在給函數原型聲明或者函數定義的時候:能夠用int *i代替 int i[]

int sum(int i[], int n);

任何狀況下,int *i;都表示i是指向int類型的指針

int i[];能夠表示i是指向int的指針(只在函數原型聲明和函數定義的時候可用),還有能夠表示i是數組i的首地址。

必須掌握以下四個等價方式(函數原型聲明能夠省略參數名字),注意只有在函數原型聲明或者函數定義頭的時候int *i和int i[]是等價的。

int sum(int i[], int n);

int sum(int [], int);//由於能夠省略參數名,故數組名能夠省去

int sum(int *i, int n);

int sum(int *, int);//指針名能夠省去

而函數定義的時候不能省略參數名字,必須掌握這兩個形式

int sum(int *ii, int num){}

int sum(int ii[], int num){}

再次注意只有在函數原型聲明或者函數定義頭的時候int *i和int i[]這種形式的是等價的。

須要明白的是:指針不論在什麼狀況下,對於採用四字節地址的計算機系統,大小都是4個字節,和其餘無關,只和計算機系統有關。仍是對於這個題,求數組元素和的函數sum(),咱們須要知道數組的起始,經過指針來肯定,也須要知道數組何時截至,經過大小size參數,不過,這裏也能夠用指針標識,標識數組的結束位置。

#include <stdio.h>
#include <stdlib.h>
#define  SIZE 5
int sum(int *, int *);
int main()
{
    int in[SIZE] = {1, 2, 3, 4, 5};
    printf("%d", sum(in, in + SIZE));//打印15
    system("pause");
    return 0;
}
int sum(int *start, int *end)
{
    int total = 0;
    while(start < end)//沒有大小參數了,那麼就用關係判斷
    {
        total += *start; //先把首元素的值加到total,而後循環每一個元素去累加
        start ++;//指針是int類型的,自增以後推動到下一個元素
    }
    return total;
}

注意:在函數定義裏,total += *start;語句裏,開始把數組首元素的值取出加到total,而後start加一,推動到數組下一個元素,繼續取出值累加到total,那麼有一個問題出現,循環截止的時候,是當start++到和end相等的時候,此時判斷爲假,則循環終止,也就是說total += *start;語句只累加到end前一個元素麼?

顯然不是的。這就說明:end實際指向了數組最後一個元素以後的第一個位置。這在c裏是合法的相似 c++標準庫裏的 vector 容器的 end()函數。

sum(in, in + SIZE);

語句裏in是數組首元素地址,而數組索引從0開始,那麼加size以後實際指向的是end元素的下一位。若是指向最後一位,應爲:

sum(in, in + SIZE - 1);

問題1三、指針運算的優先級

一個問題:判斷優先級

total += *start ++; //一元運算符*和++具備相同的優先級,結合從右向坐。注意到這裏是後綴自增,那麼應該是先把指針指向的數據加到total,而後指針自增,等價於循環體裏的兩行代碼效果

若是是前綴自增,那麼就是total += *++start ;指針先自增,而後再用自增以後指向的值累加到total。

若是是total += (*start )++;那就是賦值完成以後,指針指向的內容自增,而不是指針變量自增,效果是指針指向的地址不變,但裏面的元素變了。

注意:常用的是total += *start ++;,可是爲了清晰和方便,建議加括號

total += *(start ++);//效果同樣的。

小結:

處理數組的函數實際上用的指針爲參數,可是實際上,數組符號和指針符號均可以用。C和 C++語言中,i[SIZE]和*(i + SIZE)是等價的,不論i是數組名仍是i是指針變量。不過注意:只有當i是一個指針變量的時候,纔可使用諸如:i++的運算

問題1四、6種基本的指針操做

    int i[SIZE] = {1, 2, 3, 4, 5};
    int *p1, *p2, *p3;//聲明三個指針變量

    p1 = i;//把一個地址賦值給指針變量
    p2 = &i[2];

    printf("指針自己的值 = %p, 指針指向的內容 = %d, 指針自己的地址 = %p\n", p1, *p1, &p1);

指針之間的運算

    p3 = p1 + 4;//指針加上整數
    p1++;//指針自增
    p2--;//指針自減
    ++p2;
    p1 - p2;//指針相加減
    p1 + p2;
    p1 - 2;

運算有6種(賦值,取值,取地址,和整數加減(自增自減),比較關係,作差):

一、賦值:一般用&或者數組名(須要注意,賦值的地址應和指針類型一致,好比int類型的指針,那麼地址賦值的時候必須是int,不能是好比double類型,雖然c99許可了,可是仍是不建議)。

二、取值:間接運算符*,取出指針指向內容

三、取地址:&能夠用於指針,取出指針自己的地址

四、指針和一個整數相加或者相減:+符號,-符號, 指針的自增自減

五、兩個指針作差:

一般用於數組元素兩個元素之間的差值,求出元素之間的距離,單位是相應指針指向內容的類型的大小,好比int類型數組裏,求指針差值爲2,就是2個int類型的大小的距離。前提是同一個數組裏。不然結果可能出錯。 且在 c++裏,兩個指針作減法的結果是標準庫類型ptrdiff_t(帶符號的整數類型),在 cstddef 頭文件定義。能夠在指針上+、-0操做,指針不變。

六、指針之間的比較:能夠用關係運算符,前提是兩個指針類型相同

注意:

進行指針的增量和減量計算以後,c並不保證指針老是指向有效的元素(好比數組越界),不會檢測的。在數組裏,C只保證指向第一個元素的指針和最後一個元素後一位的指針有效。

在對指針進行取值運算時,不要對指向最後一個元素的後一位的指針取值,儘管編譯經過。

指針之間(通常都是數組的時候用,必須在同一個數組裏)能夠相減,可是不能相加!固然乘除就更離譜了……

    int i[3] = {1, 2, 3};
    int *ptr1 = &i[0];
    int *ptr2 = &i[1];
    ptr1 = ptr2 - ptr1;//能夠相減
    ptr2 = ptr2 + ptr1;// error C2110: 「+」: 不能添加兩個指針

問題1五、int array[SIZE]和int *array的區別和聯繫要明白理解(接上)

    int i[3] = {1, 2, 3};
i++;// error C2105: 「++」須要左值

在函數的聲明和定義頭裏,對數組操做的話,那麼形式參數使用形式爲int *array等價於使用int array[],當且僅當在函數原型聲明和定義頭裏。

問題1六、再次強調不能對沒有初始化的指針取值!

    int *p;//指針沒有初始化!
    *p = 5;//大大的錯誤!5賦值給指針p所指向的內容,可是指針p並無初始化,故指針p指向哪一個地址並不明確,不知道5會存儲到什麼位置,這樣取值操做的話,隨機性太大,這樣作可能對系統危害不大,多是覆蓋的之前的數據,也可能致使程序崩潰

記住:新建一個指針,系統只分配了用來存儲指針自己的內存空間,並無分配這個指針所指向的內容的存儲空間,故在使用這個指針前,必須賦一個已經分配好的內存地址給指針,而後才能取值操做,不然隨機危害太大。總之,不能對沒有初始化的指針取值!

指針的做用一是在函數間進行通訊,好比想要被調函數修改主調函數變量的值,那麼必須使用指針操做。二是在處理數組的函數裏使用。且理解一句話,指針就是數組的迭代器!

相關文章
相關標籤/搜索