1. 程式人生 > 實用技巧 >C/C++指標學習記錄

C/C++指標學習記錄

1、指標概述

  • 在學習新的知識之前,我們先回顧一下已經學習了的知識。我們已經瞭解到,在C環境下,程式裡面變數的值都是儲存在記憶體裡面。當我們要求執行的時候程式的時候,CPU才會來主動尋找存放資料那塊記憶體,然後取出來執行。那麼怎麼唯一找到那塊記憶體呢?是的,沒錯。我們通過記憶體單元地址號就可以定位相應的儲存單元了。所以指標變數其實就是儲存地址的一種變數。

  • 接下來我們在談一談為什麼我們要學習指標相關的知識。
    情景1:只是需要一個變數來儲存一個必須值。比如一個簡單的迴圈。
#include <stdio.h>
int main()
{
  //在迴圈裡面定義一個臨時整形變數。
  for(int i=3,i>=0;i--)
  {
  	printf("%d",i);
  }
  return 0;
  
}

#include <stdio.h>
int main()
{
   //在迴圈裡面定義一個臨時指標型整形變數。
   int i_=3;
   for(int *i=&i_;*i>=0;*i--)
   {
   	printf("%d\n",i);
   }
   return 0;
   
}

顯然在這種時候,使用非指標變數會更加簡單一些。

  • 情景二:函式修改引數的值。
#include <stdio.h>
void fun(int A)
{
	A=5;
}
int main()
{
	int a=3;
	fun(a);
	printf("%d",a);
	return 0;
}

執行結果

僅僅把這個引數傳進去,可以看到最終的結果並沒有改變。因為這樣傳參僅僅只是把引數的值賦值給了另外一個系統自動定義生成的變數。他們僅僅擁有相同的內容,儲存空間不再同一個地方。所以只要我們不提供返回值,那麼其實傳入的引數更我們的運算過程並沒有太大的關係。可以看一下除錯的過程證實一下我們的想法。




很明顯他們的地址不一樣。CPU是通過地址來獲取變數的值,如果地址不一樣那麼顯然和我們的想法不一致。
如果我們想要對引數本身改變,那麼就需要知道引數的地址,通過改變地址裡面儲存的值來達到我們的目的。

#include <stdio.h>
void fun(int *A)
{
	*A=5;
}
int main()
{
	int a=3;
	fun(&a);
	printf("%d\n",a);
	return 0;
}

這樣我們就可以通過傳入一個指標變數引數來達到更改引數值的目的。因為只是為了講懂這個知識點,所以用的例題也很簡單。
當然其實我們還知道一種參入引數的方式來改變引數的值,那就是傳引用。那麼接下來我們看看傳引用的本質。

#include <stdio.h>
//傳引用的本質
void fun(int &A)
{
	A=5;
}
int main()
{
	int a=3;
	fun(a);
	printf("%d\n",a);
	return 0;
}

我們先看一下,除錯的結果:
主函式裡面引數的地址:





函式裡面引數的地址:





結果呈現的是通過傳引用我們也可以直接將引數的地址傳入函式。為了更加深入的研究我們可以看一下,我們程式的反彙編:
直接傳入指標的彙編:





傳引用的彙編:





直接傳入引數:



這樣的話,我們就可以很清楚地知道,其實傳引用和傳指標的原理是一樣的。

  • 情景三:建立動態陣列。我們學習C語言的時候,環境是沒有給我們提供動態陣列這個型別的變數。所以當我們想要建立動態陣列(** 連結串列 **)就只可以使用指標變數。


    用指標建立:

#include <stdio.h>
#include <stdlib.h>
typedef struct ActiveArray
{
	int a;
	struct ActiveArray *next;
}AA;
int main()
{
	AA *aa_head;//建立一個動態陣列的頭指標
	int n;//確定動態數字的大小。
	scanf("%d",&n);
	aa_head=(AA *)malloc(n*sizeof(AA));//在記憶體申請相應大的空間。
	free(aa_head);//在推中申請的空間一定要記得釋放
	aa_head=NULL;//設定指標指向NULL。
	return 0;
}	

當然我們還可以建立單鏈表,連結串列的使用可能是指標最常用的地方了,就之後在記錄吧。