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

幾個關於數組、指針的易錯點,數組,指針易錯

編輯:C++入門知識

幾個關於數組、指針的易錯點,數組,指針易錯


指針是某個變量的地址,是一個地址

指針變量是存放指針(某個變量地址)的變量,是一個變量。

指針變量是一個變量,也有它自己的地址;這幾句話對理解指針非常有幫助。

舉例: 

int c = 76;
int *pointer = &c;

普通變量 c 和 指針變量 pointer 在內存中的形式如下圖:

指針變量pointer 有它自己在內存中的地址,見上圖黃色區域,指針變量的值存放著一個地址,見上圖紅色方框中的藍色方框中的地址,這個地址指向變量c,也即這個地址和變量c的地址相等;

我們把c,c的地址,*pointer,pointer,pointer的地址分別輸出,見下列代碼:

cout << c << endl;         //輸出:76                                         
cout << *pointer << endl;  //輸出:76                                         
cout << hex << &c << endl; //輸出:0x0012FF74                          
cout << pointer << endl;   //輸出:0x0012FF74                          
cout << &pointer << endl;  //輸出:0x0012FF90                          

 

 #---------------------------------------------------------------------------------#

指針基類型的作用:當用指針遍歷時,+1等於幾個byte取決與指針基類型;

舉例:

如上圖,指針p2 指向某個int值,int值占據4個byte大小(有些環境下占2個byte),那麼p2++的值是在p2的值的基礎之上加上4個byte找到的。

 

 #---------------------------------------------------------------------------------#

數組與指針

數組名相當於指向數組第一個元素的指針。

對於int a[4] = {1,3,5,7};

a是指向數組第一個元素的指針,即a相當於&a[0];

&a是"指向數組"的指針,&a+1將跨越16個字節;

  &a相當於管轄范圍上升了一級;

*a是數組的第一個元素a[0], 即*a等價於a[0];

  *a相當於管轄范圍下降了一級;

來看代碼,這個例子我問過兩位師兄,都沒能答對。注意標紅色的兩條輸出的區別。

復制代碼
#include<iostream>
#include<iomanip>
using namespace std;

int main()
{
  int a[4] = {1,3,5,7};
  cout << hex << a << endl;   //輸出:0028F7C4
  cout << &a << endl;         //輸出:0028F7C4
  cout << &a+1 << endl;       //輸出:0028F7D4
  cout << *(&a) << endl;      //輸出:0028F7C4
  cout << *(&a)+1 << endl;    //輸出:0028F7C8
}
復制代碼

這是數組a在內存中的存放形式,非常有助於理解。

 

如果換成二維數組,情況也類似,只是稍微復雜些;

來看個例子:

復制代碼
#include<iostream>
#include<iomanip>
using namespace std;

int main()
{
  int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
  cout << hex << a << endl;   //輸出:0xbf870830
  cout << &a[0] << endl;      //輸出:0xbf870830
  
  cout << a+1 << endl;        //輸出:0xbf870840
  cout << &a[0]+1 << endl;    //輸出:0xbf870840
  
  cout << *a << endl;         //輸出:0xbf870830
  cout << a[0] << endl;       //輸出:0xbf870830
  cout << &a[0][0] << endl;   //輸出:0xbf870830
  
  cout << *a+1 << endl;       //輸出:0xbf870834
  cout << a[0]+1 << endl;     //輸出:0xbf870834
  cout << &a[0][0]+1 << endl; //輸出:0xbf870834

  cout << &a+1 << endl;       //輸出:0xbf870860
}
復制代碼

 

第一次做這個題目幾乎很難都答對,但知道了規則之後就都能理解了,要更深入了解數組跟指針的關系和區別的話還得看其他的書。

小結一下:

數組名相當於指向數組第一個元素的指針。這裡第一個元素不單單只一個數,可能是一個小數組(如上例);

對於二維數組a,見下圖;

a相當於指向數組的第0行那個小數組;

*a等價於a[0], 相當於讓a下降了一級;

&a表示“指向二維數組”的指針,相當於上升的一級;

 

 #---------------------------------------------------------------------------------#

指針用作函數返回值時,必須保證返回的地址是有意義的!

舉例:

復制代碼
#include<iostream>
using namespace std;

int *getInt1()
{
  int value1 = 20;
  return &value1;
}

int *getInt2()
{
  int value2 = 30;
  return &value2;
}

int main()
{
  int *p, *q;
  p = getInt1();
  q = getInt2();
  
  cout << *p << endl; //輸出: 30
  return 0;
}
復制代碼

上述代碼,編譯出現警告。指針變量p存放了一個局部變量的地址,而局部變量的作用域只在函數內部,函數調用結束後即被釋放(這半句話的表述不夠准確,水平有限,暫時只能這麼描述)。

解決辦法: 將局部變量變為靜態局部變量即可。或者也可以設為全局變量(不過這明顯不是個好主意)。

int *getInt1()
{
  int static value1 = 20;
  return &value1;
}

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