gcc和gdb
【1】GNU工具
編譯工具:把一個源程序編譯為一個可執(zhí)行程序
調(diào)試工具:能對執(zhí)行程序進行源碼或匯編級調(diào)試
軟件工程工具:用于協(xié)助多人開發(fā)或大型軟件項目的管理,如make【2】gcc簡介
全稱為GNU CC ,GNU項目中符合ANSI C標準的編譯系統(tǒng)
【3】gcc編譯過程
1--- 預處理:主要進行宏替換以及頭文件的包含展開
gcc -E HelloWorld.c -o HelloWorld.i
2--- 編譯:編譯生成匯編文件,會檢查語法是否有錯誤
gcc -S HelloWorld.i -o HelloWorld.s
3--- 匯編:將匯編文件編譯生成目標文件(二進制文件)
gcc -c HelloWorld.s -o HelloWorld.o
4--- 鏈接:鏈接庫函數(shù),生成可執(zhí)行文件
gcc HelloWorld.o -o HelloWorld
【4】Gdb調(diào)試
首先使用gcc對file.c進行編譯,注意一定要加上選項‘-g’
查看文件(list)
(gdb) l
一次十行,知道顯示完為止
l 1 回到先前的位置
設置斷點 (break)
(gdb) b 行數(shù)
刪除斷點 (delete)
del 1刪除第一個斷點
查看斷點情況
(gdb) info b
查看變量值(print) 也可以查看變量的地址 p &a
(gdb) p n
單步運行 (next step)
(gdb) n
(gdb) s 進入函數(shù)
恢復程序運行 (continue)
(gdb) c
幫助
(gdb) help [command]
退出
q
gdb使用時注意事項
在gcc編譯選項中一定要加入‘-g’。
只有在代碼處于“運行”或“暫停”狀態(tài)時才能查看變量值。
設置斷點后程序在指定行之前停止
運行被調(diào)試程序,設置所有的能影響該程序的參數(shù)和變量。
保證被調(diào)試程序在指定的條件下停止運行。
當被調(diào)試程序停止時,讓開發(fā)工程師檢查發(fā)生了什么。
根據(jù)每次調(diào)試器的提示信息來做響應的改變,以便修正某個錯誤引起的問
題
***************************指針***********************
【1】指針定義
在計算機內(nèi)部存儲器(簡稱內(nèi)存)中,每一個字節(jié)單元,都有一個編號,稱為地
址。
在C語言中,內(nèi)存單元的地址稱為指針,專門用來存放地址的變量,
稱為指針變量(pointer variable)。在不影響理解的情況中,有時對地址、指針和指針變量不區(qū)分,通稱指針。
*:在定義指針變量時,只起到標識作用,在其他情況下,代表獲取指針變量內(nèi)的內(nèi)
容
&:代表取變量的地址
int *p = &a;
//如果一個指針變量指向NULL,代表不給他分配任何地址
int *q = NULL;
printf("q = %p\n", q);
輸出結果為:q=(nil)
//指針變量只能指向一塊已經(jīng)開辟的空間
//int *n = 0x12345678;
錯誤,變量的地址只能由系統(tǒng)分配,不能人為指定
//地址的運算與數(shù)據(jù)類型相關
printf("p = %p\n", p);
printf("p + 1 = %p\n", p + 1);
【2】指針與一維數(shù)組
//數(shù)組名是一個地址常量,不能改變地址
int a[6] ;
a++; 錯誤,a為地址常量,不可更改 int b[N];
b = a; 錯誤,b為地址常量,不可更改
指針的升級 int a[6] ; &a 代表整個數(shù)組a的地址,&a+1 代表移動整個數(shù)組的大小
printf("&a = %p\n", &a);
printf("&a + 1 = %p\n", &a + 1);
【3】指針與二維數(shù)組
1)指針的升級 &a 代表整個數(shù)組,&a+1 代表移動整個數(shù)組的大小 int a[3][4];
printf("&a = %p\n", &a);
printf("&a + 1 = %p\n", &a + 1);
2)二維數(shù)組的名字為行指針,指向a[ 0 ] 元素,a+1每次移動一行元素的大小 printf("a = %p\n", a);
printf("a + 1 = %p\n", a + 1); 3)指針的降級,將行指針降級為列指針
*a 代表將行指針a降級為列指針,指向元素a[0][0],*a+1,移動一個元素的大小 printf("*a = %p\n", *a);
printf("*a + 1 = %p\n", *a + 1);
4)a[0] 為列指針,指向元素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】字符指針和字符串
1)字符串自帶結束標志符‘\0’
char s1[] = "hello";
char s2[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
char s2[5] = {'h', 'e', 'l', 'l', 'o'}; 數(shù)據(jù)后沒有結束符,易發(fā)生越界訪
問
2)字符指針指向一個字符串常量,不可更改字符串的內(nèi)容,但是可以更改字符指針的
指向
【5】數(shù)組指針
數(shù)組指針:本質(zhì)上一個指針,指針指向一個數(shù)組,就是一個行指針
int (*p)[4]; //4為列數(shù)
【6】指針數(shù)組
指針數(shù)組:本質(zhì)上是一個數(shù)組,數(shù)組里面存放的是指針
int *p[2]; // [2] 為數(shù)組的長度,表示數(shù)組內(nèi)可以存儲兩個指針
【7】多級指針
多級指針:指向指針的指針
int *p = &a; int **q = &p; 【8】const
const常用來修飾指針變量或者類型
1)如果const修飾類型,則不能通過指針變量修改數(shù)據(jù) const int *p = &a;
*p = 40; 錯誤,不可通過*p訪問數(shù)據(jù)內(nèi)容
2)如果const修飾一個指針變量,則不能呢個改變這個指針變量的地址
int *const p = &a;
p = &b;錯誤,不可更改p的指向注意:const 修飾誰,誰被常量化,不可更改
******************函數(shù)********************【1】定義
函數(shù)是一個完成特定功能的代碼模塊,其程序代碼獨立,通常要求有返回值,也可以是空值。
【2】一般形式如下:
<數(shù)據(jù)類型> <函數(shù)名稱>( <形式參數(shù)說明> )
{
語句序列;
return (<表達式>);
}
其中:
<函數(shù)名稱>是一個標識符,要求符合標識符的命名規(guī)則;
<數(shù)據(jù)類型>是整個函數(shù)的返回值類型,如無返回值應該寫為void型;
<形式參數(shù)說明>是逗號”,”分隔的多個變量的說明形式,通常簡稱為形
參;
大括弧對 {<語句序列> },稱為函數(shù)體;
<語句序列>是大于等于零個語句構成的。
注意:在函數(shù)體中,表達式語句里使用的變量必須事先已有說明,否則不
能使用。
return(<表達式>)語句中表達式的值,要和函數(shù)的<數(shù)據(jù)類型>保持一致;如函數(shù)的<數(shù)據(jù)類型>為void,可以省略或者無表達式結果返回(即寫成
return ;)。
【3】函數(shù)傳參
值傳遞 :函數(shù)的傳參1:值傳遞,只是將變量的數(shù)據(jù)傳遞給行參,不會改變原來實參的數(shù)據(jù)
地址傳遞 將變量的地址傳遞給行參,改變地址的內(nèi)容,則實參也會改變
注意:數(shù)組的值傳遞,實質(zhì)為地址傳遞,改變形參的值,實參的值同樣被改變【4】命令行傳參(向main函數(shù)傳遞參數(shù))
argc:表示命令行傳參的個數(shù)
argv:表示命令行所傳的每一個參數(shù)
【5】函數(shù)指針
函數(shù)指針:本質(zhì)上是一個指針,指向一個函數(shù)
注意:函數(shù)名就是首地址
【6】指針函數(shù)
指針函數(shù):本質(zhì)上是一個函數(shù),返回值是一個指針
【7】函數(shù)指針數(shù)組
函數(shù)指針數(shù)組:本質(zhì)上是一個數(shù)組,數(shù)組里面存放的時函數(shù)指針
【8】遞歸函數(shù)
在遞歸函數(shù)中判斷是否滿足某個條件,不滿足則return 遞歸函數(shù)本身
(return myrecursion)
滿足條件則返回一個準確的數(shù)值
int myrecursion(int n){
if(n<1)
return 1;
else
return n*myrecursion(n-1);
}
【9】回調(diào)函數(shù)
將一個函數(shù)以參數(shù)的形式傳遞給某個函數(shù)。
即回調(diào)函數(shù)的其中之一或更多的形參是某個函數(shù)傳參使用函數(shù)名
int callback(int fun(int a,int b),int m,int n){ return fun(m,n);
}