標籤:C語言
梓益C語言學習總結
一、靜態變數與普通變數的區別
1.1、普通的全域變數
概念:
在函數外部定義的變數
作用範圍:
全域變數的作用範圍,是程式的所有地方。
只不過用之前需要聲明。聲明方法 extern int num; 聲明的時候,不要賦值。
生命週期:
程式啟動並執行整個過程,一直存在,直到程式結束。
注意:定義普通的全域變數的時候,如果不賦初值,它的值預設為0
1.2、靜態全域變數 static
概念:
定義全域變數的時候,前面用static 修飾。
作用範圍:
static 限定了靜態全域變數的,作用範圍
只能在它定義的.c(源檔案)中有效
生命週期:
在程式的整個運行過程中,一直存在。
注意:定義靜態全域變數的時候,如果不賦初值,它的值預設為0
2.1、普通的局部變數
概念:
在函數內部定義的,或者複合陳述式中定義的變數
作用範圍:
在函數中定義的變數,在函數中有效
在複合陳述式中定義的,在複合陳述式中有效。
生命週期:
在函數調用之前,局部變數不佔用空間,調用函數的時候,才為局部變數開闢空間,函數結束了,局部變數就釋放了。
在複合陳述式中定義的亦如此。
注意:定義局部變數的時候,如果不賦初值,它的值為隨機值
2.2、靜態局部變數
概念:
定義局部變數的時候,前面加static 修飾
作用範圍:
在它定義的函數或複合陳述式中有效。
生命週期:
第一次調用函數的時候,開闢空間賦值,函數結束後,不釋放,以後再調用函數的時候,就不再為其開闢空間,也不賦初值,
用的是以前的那個變數。
注意:
1:定義普通局部變數,如果不賦初值,它的值是隨機的。
2:定義靜態局部變數,如果不賦初值,它的值是0
3:普通全域變數和靜態全域變數如果不賦初值,它的值為0
二、標頭檔路徑
#include<> 在系統路徑下尋找標頭檔
#include“ ” 在目前的目錄下尋找標頭檔
三、a++ 先調用a再把它的值加一,++a 先把a的值加一再調用a
四、宏定義 #define
1、宏定義後不加分號,宏定義的值不能改變
2、宏是在先行編譯的時候進行替換,無變數,不佔記憶體
3、宏定義可以防止不知含義的數字出現,方便修改
4、可以定義任何類型
不帶參宏
#define PI 3.14
在先行編譯的時候如果代碼中出現了PI 就用 3.14去替換。
宏的好處:只要修改宏定義,其他地方在先行編譯的時候就會重新替換。
終止宏:#undef PI //終止PI的作用
帶參宏(宏函數)
#define S(a,b) (a)*(b)
注意帶參宏的形參 a和b沒有類型名,
S(2,4) 將來在預先處理的時候替換成 實參替代字串的形參,其他字元保留,(2) * (4)
五、條件編譯(選擇性編譯)
#ifdef AAA
程式碼片段一
#else
程式碼片段二
#endif
如果在當前.c ifdef 上邊定義過AAA ,就編譯程式碼片段一,否則編譯程式碼片段二
常用在.h檔案頭部,如:檔案fun.h開頭寫上
#ifndef FUN_H
# define FUN_H
.......程式碼片段.......
# endif
防止fun.h檔案被重複引用
六、動態庫和靜態庫
一:動態編譯
動態編譯使用的是動態庫檔案進行編譯
gcc hello.c -o hello
咱們使用的是動態編譯方法
二:靜態編譯
靜態編譯使用的靜態庫檔案進行編譯
gcc -static hello.c -o hello
三:靜態編譯和動態編譯區別
1:使用的庫檔案的格式不一樣,動態編譯使用動態庫,靜態編譯使用靜態庫
注意:
1:靜態編譯要把靜態庫檔案打包編譯到可執行程式中。
2:動態編譯不會把動態庫檔案打包編譯到可執行程式中,它只是編譯連結關係
製作靜態庫:.c檔案mylib.c
gcc -c mylib.c -o mylib.o產生mylib.o
ar rc libtestlib.a mylib.o產生靜態庫libtestlib.a
注意:靜態庫起名的時候必須以lib開頭以.a結尾
編譯器:gcc -static mytest.c libtestlib.a -o mytest
製作動態連結程式庫:gcc -shared mylib.c -o libtestlib.so //使用gcc編譯、製作動態連結程式庫
動態連結程式庫的使用:gcc mytest.c libtestlib.so -o mytest
七、
出現段錯誤,一定是指標用錯了
定義字元數組時,記得初始化為空白 char str[20]=" ",將空間定義大點,後期可以進行最佳化
八、建立鏈表的兩種方法
頭插法-有傳回值
(STU *)link_creat_head(STU *p_head,STU *p_new)
{
if(p_head==NULL)//當第一次加入鏈表為空白時,head執行p_new
{
p_head=p_new;
p_new->next=NULL;
}
else//第二次及以後加入鏈表
{
p_new->next=p_head;//將新申請的節點加入鏈表
p_head=p_new;
}
return p_head;
}
尾插法-無傳回值
void link_creat_head(STU **p_head,STU *p_new)
{
STU *p_mov=*p_head;
if(*p_head==NULL)//當第一次加入鏈表為空白時,head執行p_new
{
*p_head=p_new;
p_new->next=NULL;
}
else//第二次及以後加入鏈表
{
while(p_mov->next!=NULL)
{
p_mov=p_mov->next;//找到原有鏈表的最後一個節點
}
p_mov->next=p_new;//將新申請的節點加入鏈表
p_new->next=NULL;
}
}
鏈表逆序:每個節點的next指標的方向調頭反向
STU *reverse(STU *head)
{
STU *pf,*pb,*r;
pf=head;
pb=pf->next;
while(pb!=NULL)
{
r=pb->next;
pb->next=pf;
pf=pb;
pb=r;
}
head->next=NULL;
head=pf;
return head;
}
九、fgets
stdout、stdin 標準輸入輸出緩衝區指標
用fgets代替scanf進行輸入讀取,避免緩衝區溢位
buf1[20]=" ";
fgets(buf1, sizeof(buf1)-1, stdin);
buf1(strlen(buf1)-1)='\0';
printf("%s\n", buf1);
如果和scanf一起用,要先讀出緩衝區中的\n, char ch=0; scanf("%c", &ch);
梓益C語言學習總結