天天看點

C++自學20:指針/指針的指針/const

指針,32位系統一定占據4個位元組,64位系統一定占8個位元組

定義指針

int* a{};
std::cout<<a<<std::endl;
int *b{};
std::cout<<b<<std::endl;      

上面定義了一個int類型的指針,a表示指針起始位址,因為int的大小是4,是以int*的意思是指針每次移動都移動4個位元組

int a = 666;
//擷取a的記憶體位址,是pa,C++中使用&符号來擷取指定變量的記憶體位址
int* pa = &a;
//在pa前面加個星号,*pa叫做間接運算符,C++中使用間接運算符來修改記憶體的值
*pa = 777;
std::cout << a;      

指針數組(注意不是數組指針)

int a[3]{11,22,33};
int * pa[3]{};
for (int i = 0; i < 3;i++) {
  pa[i] = &a[i];
}
for (int* p:pa) {
  std::cout << p << std::endl;
}      

關于指針的移動

int  a = 9999;
long long b = 9999;
// 挪動1次指針,指針走4個位元組,因為int是4個位元組
std::cout << &a << std::endl;
std::cout << &a+1 << std::endl;
// 挪動1次指針,指針走8個位元組,因為longlong是8個位元組
std::cout << &b << std::endl;
std::cout << &b+1 << std::endl;      

先說指針類型轉換,下面示範将一個int類型的指針轉換成char類型的指針

int main()
{
  int a = 1;
  char *p = (char*)&a;
  std::cout << &a <<"\n";
  std::cout << p << "\n";
}      

上面的代碼第二次列印的時候會列印出亂碼,

因為是個char是字元類型,是以cout把char類型的指針當做字元串來處理,列印的時候會以’\0’結束,但是指針是沒有’\0’的,是以亂碼,此時應該将上面的代碼再次轉換成void類型的指針,如下

int main()
{
  int a = 1;
  char *p = (char*)&a;
  std::cout << &a <<"\n";
  std::cout << (void*)p << "\n";
}      

這樣兩次列印的位址就是相同的了

為指針區分不同的類型,意義在于從一個變量的首位址讀取資料的時候,具體讀多長。比如一個CPU可以根據該指針是int類型,那麼一次就讀取4個位元組的長度,如果是char類型,就讀取1個位元組的長度

是以int類型的指針++一次,是加4個位元組,而char類型指針++一次是1個位元組

指針自增

int a = 666;
int* pa = &a;
std::cout << pa << std::endl;
// 注意這個寫法,先列印pa所指向的值,然後指針再加1
std::cout << *pa++ << std::endl;
std::cout << pa << std::endl;      

指針的指針,最後一個指針,叫做基址,就是下面代碼的ppa,修改**ppa的時候,并不是修改pa,而是直接修改了它最終指的那個值

int a = 666;
int* pa = &a;
int** ppa = &pa;
**ppa=777;
std::cout << *pa << std::endl;//列印出777      

常量的指針(const int*)

const int a = 666;
const int* pa = &a;
//*pa = 55;此處報錯,不允許修改a的值
std::cout << *pa << std::endl;
//--------------------------
//是以我們定義一個int類型指針,而不是常量int指針,像下面這樣
int* pb = (int*)&a;
*pb = 55;
std::cout << *pb << std::endl;
// 然後接下來我們繼續輸出a的值,很有意思,a的值并沒有被改
std::cout << a << std::endl;//666      

指針常量(注意不是常量的指針)

int a = 666;
int b = 0;
int* const pa = &a;
//pa = &b;此處報錯,pa隻能隻想a所在的位址,不可以在指向其他位置,但是a的值可以改
std::cout << *pa << std::endl;      

個人總結:關于星号與const的優先級,星号的優先級更高,星号修飾什麼,就是什麼的指針,比如星号修飾const int,那麼這就是常量的指針,星号隻修飾int,那麼這是int類型的指針,知道該指針類型了,然後再看const就好記了

一維數組指針

int a[2] = { 11,12 };
int* pb = a;
//列印出12
std::cout << pb[1]<< std::endl;      
// 定義一個2行,3列的數組
int a[2][3] = {
  {11,12,13},
  {21,22,23}
};
//此處的3,就是列數,上面數組是幾列,此處就要寫幾
int (*pa)[3]=a;
//因為這是數組指針,是以它有下面這種特性
std::cout << pa[0][2] << std::endl;//列印出13
//下面這行代碼強轉,也可以與一維數組一樣,隻不過這樣沒有了多元數組的指針特性,僅此而已
int* pb = (int*)a;      
int a[2][3] = {
  {11,12,13},
  {21,22,23}
};
int(*pa)[3] = a;
std::cout << pa << std::endl;
//因為定義了每行三條資料
//是以此處比上一行多出12
std::cout << pa+1 << std::endl;      

繼續閱讀