什么是指標
指標是C語言的核心概念,也是C語言的特色和精華所在,更是初學者學習的難點所在,掌握了指標,才談得上是真正掌握了C語言,指標也就是記憶體地址,指標變數是用來存放記憶體地址的變數,不同型別的指標變數所占用的存盤單元長度是相同的,而存放資料的變數因資料的型別不同,所占用的存盤空間長度也不同,有了指標以后,不僅可以對資料本身,也可以對存盤資料的變數地址進行操作,
指標的作用
1、指標就是指向一個特定記憶體地址的一個變數,指標可以有效地表示復雜的資料結構、動態分配記憶體、高效地使用陣列和字串、使得呼叫函式時得到多個回傳值等,指標的應用往往與陣列聯系在一起,是最頻繁的,也是最基礎的,在定義陣列和函式時,系統都會為其自動分配一個指向其首地址的指標,對于一個陣列,其名稱就是一個指標變數,
2、指標只是一個變數,它存盤一個記憶體地址,如果傳入一個地址,比傳入一個副本效率要高,因為少了一個拷貝程序,
3、指標能夠有效的表示資料結構,能動態分配記憶體,能較方便的使用字串,有效的使用陣列,
4、指標直接與資料等的儲存地址有關,是比較重要的,比如,地址傳遞比值傳遞高效,因為值傳遞先從實參的地址中提出值,再賦值給形參帶入函式計算;而指標則把形參的地址直接指向實參地址,使用時直接提出資料,使效率提高,特別在頻繁賦值等情況下,缺點是在函式中也可以改變其值,
指標的優點
1.可以提高程式的編譯效率和執行速度減小系統開銷,使程式更加簡潔,
2.通過指標被呼叫函式可以向呼叫函式處回傳除正常的回傳值之外的其他資料,從而實作兩者間的雙向通信,
3.利用指標可以實作動態記憶體分配(例如:動態陣列),
4.指標還用于表示和實作各種復雜的資料結構(例如:鏈表,樹),從而為撰寫出更加高質量的程式奠定基礎,
5.利用指標可以直接操縱記憶體地址,從而可以完成和匯編語言類似的作業,
6.讓程式代碼更加便利接觸硬體控制等…
指標的缺點
指標可以操作任意記憶體,所以指標很靈活、很強大,但也引入了復雜性,并且申請記憶體之后需要手動釋放如果不釋放則會造成記憶體泄漏(可以使用智能指標來防止記憶體泄漏后面講),
指標的型別
我們都知道,變數有不同的型別,整型,浮點型,字符型等等,那指標有沒有型別呢?其實是有的!比如
int *p; //定義一個int 型指標變數變數名為p
舉例:
int* p; //可以指向一個int型變數或者一個int型陣列
float* p; //可以指向一個float型變數或者一個float型陣列
double* p; //可以指向一個double型變數或者一個double陣列
char* p; //可以指向一個char型變數或者一個char陣列
void* p; //可以指向任意變數使用時需要強制轉換為該指標所指變數的型別
示例:
#include<stdio.h>
int main(void)
{
int* int_p; //可以指向一個int型變數或者一個int型陣列
int A = 10;
int AA[10] = { 1,2,3,4,5,6,7,8,9,10 };
int_p = &A; //將int_p指向A的地址
printf("A的值為:%d A的地址為:%p 指標int_p指向A后 int_p所儲存的地址為:%p *p的內容為:%d ", A, &A, int_p, *int_p);
//當指標指向一個變數時可以通過 *int_p=666時,int_p所指向的那個變數的值也會等于666
*int_p = 666;
printf("*int_p=666 后 A的內容為:%d\n\n", A);
//注意:AA和AA[0]意思一樣!!
int_p = AA; //將int_p指向AA的首地址,相當于int_p=AA[0];
//注意:AA和AA[0]意思一樣!!!
printf("陣列AA的值為:%d 陣列AA的地址為:%p 指標int_p指向AA后 int_p所儲存的地址為:%p *int_p的內容為:%d\n\n", AA[0], &AA, int_p, *int_p);
//重點:當p指向一個變數時 輸出p表示 輸出p所指向的 變數的地址(記住是:"變數的地址" ), 輸出*p表示 輸出p所指向的 變數的內容(記住是:"變數的內容" );
printf("現在int_p已經指向了陣列AA, 現在用*int_p的方式輸出陣列AA的內容 \n\n");
printf("輸出為: ");
for (int i = 0; i < 10; i++, int_p++) //i是用來計數, int_p++的意思為:每運行一次int_p就往后移動一個單位(這里單位的意思是:當指標為int型時單位就為4,當指標為double型時,一個單位就為8 );
{
printf("%d ", *int_p);
}
//char指標與int 型指標類似,double和float和上面的例子中的int型指標用法幾乎一模一樣,下面講解char和void型指標
char ch = 'A';
char* char_p;
char_p = &ch;
printf("\n\nch的值為:%c ch的地址為:%p 指標char_p指向ch后 char_p所儲存的地址為:%p *char_p的內容為:%c\n\n", ch, &ch, char_p, *char_p);
//char型指標也可以指向一個字符組
char_p = (char *)"AAAA"; //有些編譯器不需要強制型別轉換,可以直接char_p="AAAA";
//注意char型指標指向一個字串輸出時不需要像其他型別(例如:int float)一樣在指標前加 * (如果char 型指標指向一個字符陣列用*char_p進行輸出 這是錯的)
printf("指標char_p指向一個字串\"AAAA\"后 char_p所儲存的地址為:%p char_p的內容為:%s\n\n", char_p, char_p);
//void型指標賦值或輸出指標所指的變數內容是都需要進行強制型別轉換
void* void_p;
void_p =(char *) "AAAAA";
printf("將\"AAAAA\"進行強制型別轉換賦給void_p 例:void_p =(char *) \"AAAAA\"; (char *)void_p的輸出結果為:%s\n\n", (char *)void_p);
int Num = 666;
void_p =(int *) &Num;
printf("將int型變數Num進行強制型別轉換賦給void_p 例:void_p =(int *) &Num; *((int *)void_p)的輸出結果為:%d ", *((int *)void_p));
}
運行結果:

陣列和指標的區別與聯系
這位大佬寫的很好也很詳細,這部分就看他的吧
指標與陣列
指標與陣列的關系 我們可以從下面這個方面入手,在C語言創建之初,很大一部分C語言的使用者是編譯器的設計者,所以為了迎合這些人的口味兒,C語言做了很多特定的規則,這些規則后來在標準化的程序中被委員會采納,成了語言標準的一部分,具體到指標與陣列這一塊兒,我們同樣從兩個方面來看,一是作為一個語言,陣列是必須要支持的一種陣列型別,原因很簡單,陣列是線性表的直接體現,而從編譯器設計者的角度來看,如果為陣列專門設計一套實作標準會非常繁雜(事實上,后來C++完成了這一任務,它就是標準庫中的vector容器),這一對矛盾最后以雙方的相互妥協得以解決,而解決方法就是利用現有的指標來間接實作陣列,然而,陣列與指標終究不是一個東西,所以,語言在設計程序中就必須在二者之間和稀泥,到最后,就形成了這樣一對令人頭大的冤家,了解了這一背景,你就不會為他倆撲朔迷離的關系而感到驚訝了,
對于編譯器而言,一個陣列是一個地址,一個指標是一個地址的地址,
陣列要么在靜態存盤區被創建(如全域陣列),要么在堆疊上被創建,陣列名對應著(而不是指向)一塊記憶體,其地址與容量在生命期內保持不變,只有陣列的內容可以改變,
//可以被更改的值叫左值,不可以被更改值的叫右值
void main(void)
{
int a[10];
a ++;//錯誤,a是左值,不能更改
}
指標可以隨時指向任意型別的記憶體塊, 遠比陣列靈活,但也更危險,下表是指標和陣列一個簡單的比較
陣列和指標的優勢
陣列的優勢
1.保存資料
2.直接訪問資料
3.用于存盤數目固定且型別相同的資料
4.編譯器自動分配和洗掉
5.自身即為資料名
指標的優勢
1.保存地址
2.間接訪問資料,先取得指標的內容,然后以它為地址,取得資料
3.通常用于動態資料結構(如鏈表)
4.動態的分配和洗掉,相關函式為malloc()和free() C++中new和delete
5.通常指向隱式資料(如通過malloc或new動態分配的記憶體)
指標和陣列都可以在初始化的時候賦予字串常量,盡管看上去一樣,底層機制卻不同,指標在定義的時候,編譯器并不會為指標所指向的物件分配記憶體空間,它只是分配指標變數的空間(32位的系統給指標分配的記憶體為4位元組,64位的系統給指標分配的記憶體為8位元組),除非以一個字串常量對其進行初始化,下面的定義創建了一個字串常量(為其分配了記憶體空間)
char* char_p = "abcde";
在ANSI C中,初始化指標時所指向的字串被定義為只讀,如果想通過指標修改字串的
時候,會產生未定義的行為(通常編譯時就會報錯),
char型陣列也可以用字串常量進行初始化,但是其內容可以被修改,
內容的復制和比較
不能對陣列進行位元組復制和比較,對于兩個char型陣列a, b, 不能用b = a進行復制,而應當使用標準庫函式strcpy(),也不能使用if(b == a)進行比較,應當使用strcmp(),
而對于指標p,如果要想將陣列a中的內容復制,要先申請一塊記憶體區域(malloc(strlen(a))+1),然后使用strcpy()進行拷貝,
指標與陣列的區別: C語言把記憶體劃分成四個區,它把一般的變數和陣列等存在于記憶體中的堆疊區,所以陣列在C語言的定義中只是一組同型別的普通變數,即使這個變數有可能是指標,所以他的作用比指標小的很多,而指標可以指向任何區的任何資料,所以就會覺得指標和陣列名很像,但是必須要注意的是,陣列名只是指標中的一種,它是指標中只指向堆疊區的且指標的移動范圍是有限的,即陣列長度,而且陣列在定義之初就已經有了自己的記憶體,一般的指標如果未指向某一個記憶體塊時,它是沒有自己的記憶體的,即所謂的野指標,
聯系:如上面所說,陣列只是定義在堆疊區的一個連續變數,它的首地址就是一個指標,
總結:不僅陣列有指標,所有變數都有指標,指標說白了就是記憶體中的地址,就像一個房間必須有一個房間號,在C/C++語言中定義一個指標,就是在堆疊區開辟一個記憶體空間用來存放它指向的記憶體地址,然后給指標賦值,就是把地址值賦值給剛才開辟的記憶體空間,然后通過訪問該記憶體中的地址值來間接訪問該地址下存放的資料,如果該地址值指向的是一塊靜態存盤區,如字串常量等,當然就不可以修改指向的內容啦,
陣列指標
定義 int (*p)[n];
()優先級高,首先說明p是一個指標,指向一個整型的一維陣列,這個一維陣列的長度是n,也可以說是p的步長,也就是說執行p+1時,p要跨過n個整型資料的長度,
大小:一個int型指標長度的空間
如要將二維陣列賦給一指標,應這樣賦值:
int a[3][4];
int (*p)[4]; //該陳述句是定義一個陣列指標,指向含4個元素的一維陣列,
p=a; //將該二維陣列的首地址賦給p,也就是a[0]或&a[0][0]
p++; //該陳述句執行過后,也就是p=p+1;p跨過行a[0][]指向了行a[1][]
所以陣列指標也稱指向一維陣列的指標,也稱行指標,
指標陣列
定義 int p[n];
[]優先級高,先與p結合成為一個陣列,再由int說明這是一個整型指標陣列,它有n個指標型別的陣列元素,這里執行p+1時,則p指向下一個陣列元素,這樣賦值是錯誤的:p=a;因為p是個不可知的表示,只存在p[0]、p[1]、p[2]…p[n-1],而且它們分別是指標變數可以用來存放變數地址,但可以這樣 p=a; 這里p表示指標陣列第一個元素的值,a的首地址的值,
大小:n個int *的資料空間
如要將二維陣列賦給一指標陣列:
int *p[3];
int a[3][4];
p++; //該陳述句表示p陣列指向下一個陣列元素,注:此陣列每一個元素都是一個指標
for(i=0;i<3;i++)
p[i]=a[i]
這里int *p[3] 表示一個一維陣列記憶體放著三個指標變數,分別是p[0]、p[1]、p[2]
所以要分別賦值,
函式指標
什么是函式指標?
函式指標大家了解一下就行了,用得不多,但一定要認識它,
什么是函式指標
如果在程式中定義了一個函式,那么在編譯時系統就會為這個函式代碼分配一段存盤空間,這段存盤空間的首地址稱為這個函式的地址,而且函式名表示的就是這個地址,既然是地址我們就可以定義一個指標變數來存放,這個指標變數就叫作函式指標變數,簡稱函式指標,
那么這個指標變數怎么定義呢?雖然同樣是指向一個地址,但指向函式的指標變數同我們之前講的指向變數的指標變數的定義方式是不同的,例如:
int(*p)(int, int);
這個陳述句就定義了一個指向函式的指標變數 p,首先它是一個指標變數,所以要有一個“*”,即 ( *p);
其次前面的 int 表示這個指標變數可以指向回傳值型別為 int 型的函式;后面括號中的兩個 int 表示這個指標變數可以指向有兩個引數且都是 int 型的函式,所以合起來這個陳述句的意思就是:定義了一個指標變數 p,該指標變數可以指向回傳值型別為 int 型,且有兩個整型引數的函式,p 的型別為 int(*)(int,int),
所以函式指標的定義方式為:
函式回傳值型別 (* 指標變數名) (函式引數串列);
“函式回傳值型別”表示該指標變數可以指向具有什么回傳值型別的函式;“函式引數串列”表示該指標變數可以指向具有什么引數串列的函式,這個引數串列中只需要寫函式的引數型別即可,
我們看到,函式指標的定義就是將“函式宣告”中的“函式名”改成“(*指標變數名)”,但是這里需要注意的是:“(*指標變數名)”兩端的括號不能省略,括號改變了運算子的優先級,如果省略了括號,就不是定義函式指標而是一個函式宣告了,即宣告了一個回傳值型別為指標型的函式,
那么怎么判斷一個指標變數是指向變數的指標變數還是指向函式的指標變數呢?首先看變數名前面有沒有“”,如果有“”說明是指標變數;其次看變數名的后面有沒有帶有形參型別的圓括號,如果有就是指向函式的指標變數,即函式指標,如果沒有就是指向變數的指標變數,
最后需要注意的是,指向函式的指標變數沒有 ++ 和 – 運算,
注意:函式指標的型別一定要與所指函式的型別相同(函式的回傳值),形參型別也要相同,當一個函式指標指向一個函式時就能像使用函式一樣使用它,
示例:
#include<stdio.h>
int fun(int Num1, int Num2)
{
return Num1 > Num2 ? Num1 : Num2;
}
int main(void)
{
int (*p)(int, int);
p = fun;
printf("66和88中最大的是:%d ", p(66, 88));
return 0;
}
運行結果如圖:

動態陣列
在實際編程中,有些陣列的個數并不能確定,如果定義得陣列過大,浪費記憶體空間,如果定義得 太小,又容納不下,也就是說,用靜態陣列的方法很難解決,那么,如何解決這個問題呢? 因為陣列名代表了該陣列的首地址,也就是指標,如果定義一個指標表示陣列名,之后將一段記憶體 空間的地址賦給該指標,就可以實作動態陣列啦!
為了實作動態陣列,必須能夠動態申請記憶體空間,C語言提供了一些記憶體管理函式,這些函式可以 根據需要動態地申請記憶體空間,以實作動態陣列的要求,
實作動態陣列的相關函式
malloc()函式
分配若干個位元組的空間,回傳一個指向該區域的指標,若系統不能提供足夠大的記憶體空間,或者初始的指向不明確,那就鐵定回傳NULL,當然了,設計指標問題錯的太離譜了,直接彈出黃框框警告,
malloc()的原型為:
void malloc(unsigned int size),size表示向系統申請的空間大小,呼叫成功將回傳一個指向void型別的指標void,常用來作為一個萬金油指標,和函式里面求導類似,不管會不會,首先去求導,
指標本質是一個被存盤著的地址,過去講過記憶體中劃分為了若干個區域,各種資料型別的值都可以分一塊上去,這個區域近似于無限大,說這句話,就是要把所謂的short,int,char看作不同型別的地址,類似于不同的學區,其依托的劃片學校不同,
廢話這么多,還是要體會到,同種型別的指標才能彼此賦值,如果要呼叫malloc的回傳值賦值給某個指標,應該先根據該指標的基型別,采用一種叫做強制型別轉換的方式,將malloc回傳的型別不明確指標,
malloc()函式的用法:
原型:void "malloc(unsigned size)
在記憶體的動態存盤區分配n個長度為size的連續空間,
malloc()函式的回傳值
申請成功,則回傳新分配記憶體塊的起始地址;否則,回傳NULL,
注意: malloc()函式的回傳值是一個無型別指標,可以指向任何型別的資料,在實際使用時,需將malloc()函 數的回傳值強制轉換成被賦值指標變數的資料型別,以免出錯,
舉個例子:
int *p=NULL;
scanf("%d",&n);
p=(int *)malloc(n*sizeof(int));//申請n個sizeof個位元組的存盤空間,也叫做記憶體吧,注意這個強制型別轉化!
free()函式
釋放malloc分配的存盤空間,原型為 void free(void *p),該函式的功能是是釋放動態申請的由指標P指向的存盤空間,該函式無回傳值,free()中引數給出的地址是函式malloc申請空間時候回傳的地址,free執行后,以前分配的由指標P指向的記憶體被清空,
Lp=(int *)malloc(sizeof(int));
free(Lp);
比方說這個組合就是一對的數值,成對出現,按照百度的解釋,free讓動態資料記憶體結構變的真的可以動態,否則就是個偽動態,只能申請,不能釋放,
標準庫中malloc函式的實作原理,要了解針對malloc的記憶體存盤結構,malloc不像全域變數一樣,不是在編譯器編譯的時候就會分配記憶體空間,而是在呼叫到malloc函式時才會分配空間,有時還會中途呼叫free函式釋放空間出來,
malloc是從堆區申請空間,函式結束后不會自動釋放,如果不人為地釋放的話,要等到程式結束后,系統才會自動回收
malloc用于向系統申請一定數量的記憶體,如果你的程式一味的申請記憶體供自己使用,那么系統可分配給其它程式的記憶體就會減少,到最后無記憶體可用,最終導致系統運行緩慢,不穩定等問題,顯然,這種只索取不奉獻的行為是不可取的因此,C語言提供了free函式,用于向系統返還借用的記憶體,有借有還,再借不難,
free()函式的用法
原型: void free(void *ptr)
free()函式的功能
釋放由ptr指向的記憶體塊(ptr是呼叫malloc()函式的回傳值),
free()函式的回傳值:無
注意: 使用malloc()函式申請的記憶體塊,操作結束后應及時使用free()函式釋放,尤其是回圈使 用malloc()函式時,如果不及時釋放不再使用的記憶體塊,很可能很快就耗盡系統的記憶體資源,從而導致 程式無法繼續運行,
示例:
//這里寫個求平均分的代碼
#include<stdio.h>
#include<stdlib.h> //使用malloc和free需要包含此頭檔案
int main(void)
{
int Num, i;
float Sun = 0;
float* Lp;
printf("請輸入學生人數:");
scanf("%d", &Num);
Lp = (float *)malloc(sizeof(float) * Num);
if (Lp == NULL)
{
printf("申請記憶體失敗!");
return -1;
}
for (i = 0; i < Num; i++)
{
printf("請輸入第%d名學生的成績:", i + 1);
scanf("%f", &Lp[i]);
}
for (i = 0; i < Num; i++)
{
Sun += Lp[i];
}
free(Lp);
printf("同學的平均分為:%.2f 分", Sun / Num);
}
結果如同:

注意: 申請成功后可以像使用普通陣列一樣使用動態陣列!
下面使用C++來實作動態陣列(如果沒有學過C++可以跳過)
new 和 delete 是 C++ 用于管理 堆記憶體 的兩個運算子,對應于 C 語言中的 malloc 和 free,但是 malloc 和 free 是函式,new 和 delete 是運算子,除此之外,new 在申請記憶體的同時,還會呼叫物件的建構式,而 malloc 只會申請記憶體;同樣,delete 在釋放記憶體之前,會呼叫物件的解構式,而 free 只會釋放記憶體,
new的用法
1.開辟單變數地址空間
使用new運算子時必須已知資料型別,new運算子會向系統堆區申請足夠的存盤空間,如果申請成功,就回傳該記憶體塊的首地址,如果申請不成功,則回傳零值,
new運算子回傳的是一個指向所分配型別變數(物件)的指標,對所創建的變數或物件,都是通過該指標來間接操作的,而動態創建的物件本身沒有識別符號名,
一般使用格式:
格式1:指標變數名=new 型別識別符號;
格式2:指標變數名=new 型別識別符號(初始值);
格式3:指標變數名=new 型別識別符號 [記憶體單元個數];
說明:格式1和格式2都是申請分配某一資料型別所占位元組數的記憶體空間;但是格式2在記憶體分配成功后,同時將一初值存放到該記憶體單元中;而格式3可同時分配若干個記憶體單元,相當于形成一個動態陣列,例如:
1.new int; //開辟一個存放整數的存盤空間,回傳一個指向該存盤空間的地址,int *a = new int 即為將一個int型別的地址賦值給整型指標a
2.int *a = new int(5) 作用同上,但是同時將整數空間賦值為5
2.開辟陣列空間
對于陣列進行動態分配的格式為:
指標變數名=new 型別名[下標運算式];
delete [ ] 指向該陣列的指標變數名;
兩式中的方括號是非常重要的,兩者必須配對使用,如果delete陳述句中少了方括號,因編譯器認為該指標是指向陣列第一個元素的指標,會產生回收不徹底的問題(只回收了第一個元素所占空間),加了方括號后就轉化為指向陣列的指標,回收整個陣列,
delete []的方括號中不需要填陣列元素數,系統自知,即使寫了,編譯器也忽略,
請注意“下標運算式”不必是常量運算式,即它的值不必在編譯時確定,可以在運行時確定,
一維: int *a = new int[100]; //開辟一個大小為100的整型陣列空間
二維: int **a = new int[5][6]
三維及其以上:依此類推.
一般用法: new 型別 (初值)
delete的用法
-
洗掉單變數地址空間
int *a = new int; delete a; //釋放單個int的空間 -
洗掉陣列空間
int *a = new int[5]; delete []a; //釋放int陣列空間
三、使用注意事項
-
new 和delete都是內建的運算子,語言本身所固定了,無法重新定制,想要定制new和delete的行為,徒勞無功的行為,
-
動態分配失敗,則回傳一個空指標(NULL),表示發生了例外,堆資源不足,分配失敗,
-
指標洗掉與堆空間釋放,洗掉一個指標p(delete p;)實際意思是洗掉了p所指的目標(變數或物件等),釋放了它所占的堆空間,而不是洗掉p本身(指標p本身并沒有撤銷,它自己仍然存在,該指標所占記憶體空間并未釋放),釋放堆空間后,p成了空指標,
-
記憶體泄漏(memory leak)和重復釋放,new與delete 是配對使用的, delete只能釋放堆空間,如果new回傳的指標值丟失,則所分配的堆空間無法回收,稱記憶體泄漏,同一空間重復釋放也是危險的,因為該空間可能已另分配,所以必須妥善保存new回傳的指標,以保證不發生記憶體泄漏,也必須保證不會重復釋放堆記憶體空間,
-
動態分配的變數或物件的生命期,我們也稱堆空間為自由空間(free store),但必須記住釋放該物件所占堆空間,并只能釋放一次,在函式內建立,而在函式外釋放,往往會出錯,
-
要訪問new所開辟的結構體空間,無法直接通過變數名進行,只能通過賦值的指標進行訪問,
用new和delete可以動態開辟和撤銷地址空間,在編程式時,若用完一個變數(一般是暫時存盤的資料),下次需要再用,但卻又想省去重新初始化的功夫,可以在每次開始使用時開辟一個空間,在用完后撤銷它,
下面使用new和delete來實作動態陣列:
//這里寫個求平均分的代碼
#include<iostream>
using namespace std;
int main(void)
{
int Num, i;
float Sun = 0;
float* Lp;
cout << "請輸入學生人數:";
cin >> Num;
Lp = new float[Num];
if (Lp == NULL)
{
printf("申請記憶體失敗!");
return -1;
}
for (i = 0; i < Num; i++)
{
cout<<"請輸入第"<<i+1<<"名學生的成績:";
cin >> Lp[i];
}
for (i = 0; i < Num; i++)
{
Sun += Lp[i];
}
cout.precision(4);
cout << "同學的平均分為:" << Sun / Num << " 分" << endl;
}
運行結果如圖:

本篇到此結束,如果本篇中有什么錯誤或者需要補充的地方歡迎大家在評論區留言,謝謝大家!
如果遇到什么問題歡迎大家進群討論或者加我qq
群內也有各種學習資料,歡迎大家一起來學習!
qq:846581636
qq群:759252814
期待你的關注
感謝大家的支持,謝謝!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/144762.html
標籤:其他
