 gcc編(bian)譯及gdb調(diao)試(shi)命令詳解
							時(shi)間:2018-08-10      來源(yuan):未(wei)知(zhi)
							gcc編(bian)譯及gdb調(diao)試(shi)命令詳解
							時(shi)間:2018-08-10      來源(yuan):未(wei)知(zhi) 
							gcc和gdb
【1】GNU工具
編(bian)譯工(gong)具(ju):把一個源(yuan)程序編(bian)譯為(wei)一個可執行程序
調(diao)試(shi)工具:能對執(zhi)行(xing)程序進行(xing)源碼或匯編級調(diao)試(shi)
軟件(jian)工程(cheng)工具(ju):用于協助多人開發或大(da)型軟件(jian)項(xiang)目的管(guan)理(li),如make【2】gcc簡(jian)介
全稱為GNU CC ,GNU項目(mu)中符合ANSI C標(biao)準(zhun)的編譯系(xi)統
【3】gcc編譯過程
1--- 預處理:主要進(jin)行宏替換以(yi)及頭文件(jian)的包含(han)展開
gcc -E HelloWorld.c -o HelloWorld.i
2--- 編(bian)譯:編(bian)譯生成匯(hui)編(bian)文件,會檢查語法是否有錯(cuo)誤
gcc -S HelloWorld.i -o HelloWorld.s
3--- 匯編:將匯編文(wen)(wen)(wen)件(jian)編譯生成(cheng)目標(biao)文(wen)(wen)(wen)件(jian)(二進制文(wen)(wen)(wen)件(jian))
gcc -c HelloWorld.s -o HelloWorld.o
4--- 鏈接(jie):鏈接(jie)庫函數,生成可(ke)執行文(wen)件(jian)
gcc HelloWorld.o -o HelloWorld
【4】Gdb調試(shi)
首先使用(yong)gcc對file.c進行編譯,注(zhu)意(yi)一(yi)定(ding)要加上選項‘-g’
查(cha)看(kan)文(wen)件(list)
(gdb) l
一次十(shi)行,知道顯示完為止
l 1 回到(dao)先前的(de)位(wei)置
設置(zhi)斷點 (break)
(gdb) b 行(xing)數
刪(shan)除斷點 (delete)
del 1刪除第一個斷點(dian)
查看斷點情況
(gdb) info b
查(cha)看變量(liang)值(print) 也可以查(cha)看變量(liang)的地址 p &a
(gdb) p n
單步運(yun)行 (next step)
(gdb) n
(gdb) s 進入函數
恢復程序運行 (continue)
(gdb) c
幫助
(gdb) help [command]
退出
q
gdb使用時注意事項
在gcc編譯選(xuan)項中一定要加入(ru)‘-g’。
只有在代碼處于“運行(xing)”或“暫停”狀態時才能(neng)查(cha)看變量值。
設置斷點后程(cheng)序在指定行之(zhi)前停止(zhi)
運(yun)行被調試程(cheng)序,設置所有(you)的(de)能影響該程(cheng)序的(de)參數(shu)和變量。
保證被調試程序在指(zhi)定的條件下(xia)停止運行。
當被調試(shi)程(cheng)序停止時,讓開發工(gong)程(cheng)師(shi)檢查發生(sheng)了什么(me)。
根據每次調試(shi)器的提示(shi)信息來做響應的改變(bian),以便修(xiu)正某個(ge)錯誤引起的問
題
***************************指針***********************
【1】指針定義
在計(ji)算機(ji)內(nei)部存儲器(簡稱(cheng)內(nei)存)中(zhong),每一個字(zi)節單(dan)元,都有一個編號(hao),稱(cheng)為地
址。
在C語言中,內存單(dan)元的(de)地址稱為指(zhi)針(zhen),專門用(yong)來存放地址的(de)變量(liang),
稱(cheng)為指針變量(pointer variable)。在不影響理解的情(qing)況中,有時(shi)對地址、指針和指針變量不區分(fen),通稱(cheng)指針。
*:在定義(yi)指(zhi)針(zhen)變量時,只(zhi)起到標(biao)識作用(yong),在其他情況(kuang)下,代表獲取指(zhi)針(zhen)變量內(nei)的(de)內(nei)
容
&:代(dai)表取(qu)變量的(de)地(di)址
int *p = &a;
//如果一個指(zhi)針變量指(zhi)向NULL,代(dai)表(biao)不給他分(fen)配任何地址
int *q = NULL;
printf("q = %p\n", q);
輸出結果為:q=(nil)
//指針(zhen)變(bian)量只能指向一塊已(yi)經開辟(pi)的空(kong)間
//int *n = 0x12345678;
錯(cuo)誤,變量的(de)地址只能由系統分配(pei),不能人為指(zhi)定
//地址的運算與(yu)數據類型相關(guan)
printf("p = %p\n", p);
printf("p + 1 = %p\n", p + 1);
【2】指針與一維數組
//數組名是(shi)一個地(di)址常量,不能改變地(di)址
int a[6] ;
a++; 錯(cuo)誤,a為地址常量,不可(ke)更改 int b[N];
b = a; 錯誤,b為(wei)地址常量,不可更改
指針的升(sheng)級 int a[6] ; &a 代表(biao)整個(ge)(ge)數(shu)組a的地(di)址,&a+1 代表(biao)移(yi)動整個(ge)(ge)數(shu)組的大小
printf("&a = %p\n", &a);
printf("&a + 1 = %p\n", &a + 1);
【3】指針與(yu)二(er)維數(shu)組
1)指針(zhen)的(de)升(sheng)級 &a 代表整個數組,&a+1 代表移動(dong)整個數組的(de)大小 int a[3][4];
printf("&a = %p\n", &a);
printf("&a + 1 = %p\n", &a + 1);
2)二維數組的名字為行(xing)指(zhi)針,指(zhi)向a[ 0 ] 元素,a+1每次(ci)移動(dong)一(yi)行(xing)元素的大(da)小 printf("a = %p\n", a);
printf("a + 1 = %p\n", a + 1); 3)指(zhi)針的降(jiang)級,將行指(zhi)針降(jiang)級為列指(zhi)針
*a 代表將行指針a降(jiang)級為列指針,指向元素a[0][0],*a+1,移動一(yi)個元素的(de)大小(xiao) printf("*a = %p\n", *a);
printf("*a + 1 = %p\n", *a + 1);
4)a[0] 為列指(zhi)針(zhen),指(zhi)向元素a[0][0], a[0]+1,移動一個元素的大小
printf("&a[0][0] = %p\n", &a[0][0]); printf("&a[0][0] + 1 = %p\n", &a[0][0] + 1);
【4】字符(fu)指針(zhen)和字符(fu)串(chuan)
1)字符串自帶(dai)結束標志符‘\0’
char s1[] = "hello";
char s2[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
char s2[5] = {'h', 'e', 'l', 'l', 'o'}; 數(shu)據后沒(mei)有結束符,易發生越界訪(fang)
問
2)字(zi)(zi)符指(zhi)針指(zhi)向一個字(zi)(zi)符串常(chang)量,不可(ke)更(geng)改字(zi)(zi)符串的(de)內容,但是(shi)可(ke)以更(geng)改字(zi)(zi)符指(zhi)針的(de)
指向
【5】數組指針(zhen)
數組(zu)指(zhi)針:本質上一(yi)個(ge)指(zhi)針,指(zhi)針指(zhi)向一(yi)個(ge)數組(zu),就是一(yi)個(ge)行指(zhi)針
int (*p)[4]; //4為(wei)列數
【6】指針(zhen)數組(zu)
指針(zhen)數(shu)組:本質上(shang)是(shi)一(yi)個(ge)數(shu)組,數(shu)組里(li)面存放的是(shi)指針(zhen)
int *p[2]; // [2] 為(wei)數(shu)組的長度,表示數(shu)組內可以存儲兩(liang)個指針
【7】多級指針(zhen)
多(duo)級指(zhi)針(zhen)(zhen):指(zhi)向指(zhi)針(zhen)(zhen)的(de)指(zhi)針(zhen)(zhen)
int *p = &a; int **q = &p; 【8】const
const常用來修飾指針變(bian)量(liang)或者類型
1)如果const修飾類型(xing),則(ze)不(bu)能通過指針變量修改數據 const int *p = &a;
*p = 40; 錯誤(wu),不可(ke)通(tong)過*p訪問數(shu)據內容(rong)
2)如果const修(xiu)飾一個(ge)指針變(bian)(bian)量,則不能呢個(ge)改變(bian)(bian)這(zhe)個(ge)指針變(bian)(bian)量的(de)地址
int *const p = &a;
p = &b;錯誤,不(bu)可(ke)更(geng)改(gai)p的(de)指向注意:const 修(xiu)飾(shi)誰,誰被常(chang)量化,不(bu)可(ke)更(geng)改(gai)
******************函(han)數********************【1】定義
函數(shu)是(shi)一個(ge)完(wan)成特定功(gong)能(neng)的代(dai)碼模塊,其(qi)程序代(dai)碼獨立,通常要(yao)求有返(fan)回值,也可(ke)以(yi)是(shi)空值。
【2】一般形式如下:
<數(shu)(shu)據類(lei)型> <函數(shu)(shu)名(ming)稱>( <形式參數(shu)(shu)說明> )
{
語句序列;
return (<表達式>);
}
其中:
<函數名稱>是一個標識(shi)符(fu),要求符(fu)合標識(shi)符(fu)的命名規則;
<數據類型(xing)>是整個(ge)函數的返(fan)回(hui)值(zhi)(zhi)類型(xing),如無返(fan)回(hui)值(zhi)(zhi)應該寫為void型(xing);
<形(xing)式(shi)(shi)參(can)數說明>是逗號”,”分(fen)隔(ge)的(de)多個(ge)變量(liang)的(de)說明形(xing)式(shi)(shi),通常簡稱(cheng)為形(xing)
參;
大(da)括弧對 {<語句(ju)序列> },稱為(wei)函數體;
<語句序(xu)列>是大(da)于等(deng)于零(ling)個(ge)語句構成的。
注意:在函數(shu)體中,表達(da)式語(yu)句里使用的變量必須事先已有說明,否則(ze)不
能使用。
return(<表(biao)達式(shi)>)語句中表(biao)達式(shi)的(de)(de)(de)值(zhi),要和函數的(de)(de)(de)<數據(ju)類型(xing)>保(bao)持一致;如函數的(de)(de)(de)<數據(ju)類型(xing)>為void,可以省略(lve)或者無表(biao)達式(shi)結果返回(即寫成
return ;)。
【3】函數傳參
值傳遞 :函數的傳參(can)1:值傳遞,只是將(jiang)變量的數據傳遞給行(xing)參(can),不會改變原來實參(can)的數據
地(di)(di)址傳遞 將變量的(de)(de)地(di)(di)址傳遞給行參(can),改(gai)(gai)變地(di)(di)址的(de)(de)內容,則實參(can)也會改(gai)(gai)變
注意:數(shu)組的值(zhi)傳(chuan)遞,實(shi)質為地(di)址(zhi)傳(chuan)遞,改(gai)變形參(can)的值(zhi),實(shi)參(can)的值(zhi)同樣被改(gai)變【4】命令行(xing)傳(chuan)參(can)(向main函(han)數(shu)傳(chuan)遞參(can)數(shu))
argc:表示命令行(xing)傳參的個數(shu)
argv:表示命令行所(suo)傳的每一(yi)個參數
【5】函數指針
函數(shu)指針:本(ben)質上是(shi)一個指針,指向一個函數(shu)
注意:函數名就是首地址(zhi)
【6】指針函數
指針函數:本(ben)質上是一(yi)個函數,返回值是一(yi)個指針
【7】函(han)數(shu)(shu)指針數(shu)(shu)組
函(han)數(shu)指針數(shu)組:本質(zhi)上(shang)是一個(ge)數(shu)組,數(shu)組里面(mian)存放(fang)的(de)時函(han)數(shu)指針
【8】遞歸(gui)函數(shu)
在遞歸(gui)(gui)函(han)數(shu)中判斷是否(fou)滿足(zu)某個條件,不滿足(zu)則return 遞歸(gui)(gui)函(han)數(shu)本(ben)身(shen)
(return myrecursion)
滿(man)足(zu)條件則返(fan)回一個準(zhun)確的數值(zhi)
int myrecursion(int n){
if(n<1)
return 1;
else
return n*myrecursion(n-1);
}
 
【9】回調函數(shu)
將一個函(han)(han)數(shu)以參數(shu)的形式傳遞給某(mou)個函(han)(han)數(shu)。
即回調(diao)函(han)(han)數(shu)的其中之一或(huo)更多的形參是某個函(han)(han)數(shu)傳參使用函(han)(han)數(shu)名(ming)
int callback(int fun(int a,int b),int m,int n){ return fun(m,n);
}

