C基礎入門


一、基本概念

1、C語言區分大小寫;
2、注釋/*里邊的所有內容都是注釋*/,或者//單行注釋;
3、printf() 打印,f表示format;scanf()輸入;
4、變量必須要有聲明,一次聲明可同時聲明多個變量並同時賦初值,每個變量之間用,號隔開;(當試圖訪問未初始化的變量時,可能產生無意義的數值或者讓程序崩潰)
5、定義常量約定全使用大寫字母(例:#difine NUMBER 11)
6、變量命名(也叫標識符)規則:
(1)可以含有字母、數字、下划線;
(2)只能以字母或下划線開頭;
7、多行代碼可用\符號進行連接;
8、把C程序轉換為機器可執行的形式,通常包括預處理、編譯、鏈接三個步驟;
預處理:預處理器執行以#開頭的指令;
編譯:把程序翻譯成機器指令;
鏈接:把由編譯器產生的代碼和所需要的其他附加代碼整合在一起;
9、可以把C程序看成是一連串的記號(token),包括:標記符、標點符號、關鍵字、字符串字面量;
10、標識符的長度理論上是沒有限制的,但超過63(C99)個字符編譯器可能無法識別;
11、邏輯運算符(!,&&,||)運算的結果是0和1,會將任何非零值操作數作為真值處理,任何0值操作數作為假值處理;
12、switch語句對分支的順序沒有要求,可以把default放在最前邊,多個分支語句可以放在同一組執行語句的前邊,用於表示這些情況都執行這相同的操作(例case 1: case 3: case 4: 語句;)
13、#define TRUE 1 定義一個常量;

 

二、數據類型

int                  整型,默認是有符號的;讀寫:%d
unsighed int          無符號整型,長度為2的32次方,但在老的CPU上也可能是16位;讀寫:%u/%o/%x
short int            短整型,默認是signed,即有符號的;讀寫:%hd,無符號讀:%hu/%ho/%hx;
unsigned short int     無符號的短整型,short和unsigned的位置可互換;長度為2的16次方;
long int            長整型;為了強制編譯器把常量作為長整數來處理可以在后邊加一個L或l(如:14L);讀寫:%ld,無符號的讀寫:%lu/%lo/%lx
unsigned long int      無符號的長整型,長度為2的64次方;為了指明常量為無符號的可在常量后加U或u;
C中整型包括8進制,10進制,16進制,8進制以0開頭,16進制以0x開頭(不區分大小寫),且這都只是整數的書寫形式,存儲都是以2進制存儲的,不同的進制可同時使用(如:10+023+0x21)

float                單精度浮點數;精度為6位數字;浮點常量必須包含小數點或指數,但小數點前后可為空,會自動補齊一個0; 讀寫可用%f/%e/%g
double               雙精度浮點數;精度為15位數字;讀:%lf/%le/%lg;寫:%f/%e/%g;
long double          擴展精度浮點數;讀寫:%Lf/%Lg/%Le;

char                字符類型(實質是int 類型的);讀寫:%c,對於單個字符的讀寫可用getchar()和putchar()函數來實現;

1、數據的隱式轉換級:short int -> unsigned short int -> int -> unsigned int -> long int -> unsigned long int -> float -> double -> long double
2、強制類型轉換:(類型名)表達式 (例:(int)x;)
3、類型定義: typedef 類型名 自定義類型名;使用后自定義類型名就可以作為一個和系統類型一樣的類型使用;(另一種方法可使用宏來將一個已有的類型名綁定到自定義名字上,如 #define BOOL int)
4、sizeof()函數可獲取程序存儲相應數據所需空間的大小;

(一)數組array

1、聲明: type name[num];
2、可在聲明時給定初值{1,2,3},如果給的初值數量不及num,會自動以0來補齊,但初值不能全為空{},至少需要有一個元素;
3、如果給定了初值可以不指定num,C會自動根據給定的初值數量來確定num;
4、給定初值時可用{[2]=6,8,[7]=7}的方式來給指定位置的元素賦值;但這樣會讓初值賦值位置跳到指定位置上,如上邊的8賦給的位置就是3,其他位置都以0補齊;如果沒有給定num,上例中自動生成的num就會是8;
6、C語言不要求檢查下標的范圍,所以即使給出了超出索引的下標,程序也不會報錯;
7、使用scanf("%d",&a[i]);可對某個元素直接使用取址符;
8、使用sizeof(a)/sizeof(a[0])來取得一個數組的元素個數;
9、數組可以是多維的(例:int x[2][3],給此二維數組初值{{1,2,3},{2,3,4}},也可省略里邊的花括號,但這樣比較危險,程序會依次給相應位置的元素賦值;)
10、不能使用數組a=數組b的方式把b的值直接復制到a,最簡單的方法是使用一個循環,使用它們的每一個元素都相等才行;或者使用memcpy(a,b,sizeof(a))函數進行復制;

(二)結構、聯合、枚舉

1、結構的聲明:

struct structName {
  typename name1;
  typename name2;
  ...;
}structN1,
structN2 = {value1,value2,...},
structN3 = {.name1 = value3, .name2 = value4,...}
structN4 = {.name1 = value5,value6,...};

每個結構都有一個獨立的命名空間,所以不同結構都可以使用相同的變量名字;

結構也可以不要structName,但是這樣如果有多個結構就無法區分;
可以在聲明結構的同時實例結構並初始化,如structN1,初始化方式可如示例的幾種,初始化中未涉及的成員值都會被設為0;也可以后再實例(示例:struct structName structN5,每次都需要加上關鍵字struct)
上例中的.name1式樣的點號和成員名稱的組合稱為 指示符,點號的運算優先級高於取址符&,所以 "&structN1.name1"表示的是structN.name1的地址;
聲明結構時最后的分號";"是必不可少的,即使聲明同時一個實例也沒有,也必須要在}號后加一個分號
2、用typedef來定義一種新的類型名:

typedef  struct {
    typename name1;
    typename name2;
    ...;
}structName;

這樣一個structName就相當於一種數據類型,實例時可如int一樣使用,同時也一定不能在前邊加struct關鍵字了;不過我們一般不使用這種方式聲明結構;
3、數組可以有結構作為元素,結構也可以包含數組和結構作為成員;
4、聯合的聲明:

union{
    typename name1;
    typename name2;
    ...;
}unionN1,
 unionN2{.name2=value1};

聯合可以有多個成員,但他只會存儲一個成員的值,當給基中一個成員賦新值的時候,其他成員的值就會被抹掉,因為一個聯合只有所有成員中最大成員所需要存儲空間的大小,同時只能存儲一個元素,所以在初始化union時只能初始化一個成員。
5、枚舉的聲明:

enum enumName{
    NAME1,
    NAME2 = const,
    ...
}enumN1;

和struct類似,在以后實例的時候需加上關鍵字enum(如:enum enumName enumN3;)
也可以用typedef來定義一個類型:
聲明:typedef enum { NAME1,NAME2 }enumName;
這樣在實例這個枚舉時也不需要在前邊加關鍵字enum了;
6、枚舉常量的名字的作用域范圍是全文件,不同於結構或聯合的獨立作用域;但是如果枚舉常量聲明在函數體內,那么它的常量對外部函數來說是不可見的;

三、格式化輸入、輸出(printf,scanf)

1、格式串包含普通字符和轉換說明,轉換說明以%開頭;
2、轉換說明格式:%-m.pX
m表示顯示的最少字符數量;.p表示顯示小數點后的位數,依賴於m;-表示右對齊,如果沒有則默認左對齊;
3、%d 表示十進制整數,如果scanf()用%i可匹配八進制和十六進制的整數;
%e 表示指數,
%f表示定點十進制浮點數,
%g 表示指數形式或者定點十進制形式浮點數;
4、scanf() 需使用取址符&來對所輸入的值進行變量名關聯; 例:scanf("please enter two number %d,%d",a,b)

四、循環

1、for循環中的條件表達式都可以省略,當省略掉第一個和第三個表達式的時候就和while循環一樣的效果;
2、for語句聲明的變量不可以在循環外訪問;
3、for語句可聲明多個變量,只要它們的類型相同;
4、break語句只能跳出一層嵌套;
5、goto語句可以跳轉到函數中任何有標號的語句處(標號語句示例,標識符(自定義):語句);goto語句和執行語句必須在同一個函數中;
6、for循環的變量改變是在所有語句都運行完畢后再執行的。

五、函數

1、函數不能返回數組;但是可以數組為參數傳遞給函數,但不會檢查數組長度,所以數組參數不用給長度,但多維數組除了第一維,其他都需要給定長度;
2、C語言允許在實際參數的類型與形式參數的類型不匹配的情況下進行函數調用,編譯器會執行默認的實際參數提升;
3、在main函數中執行return會終止程序,在任何地方調用exit函數都會終止程序;
4、C語言允許函數遞歸調用函數本身;
5、不允許一個函數的定義出現在另一個函數體中(嵌套);
6、函數原型中的形式參數的名字可以與函數定義中給出的名字不同;
7、局部變量的存儲單元在包含該變量的函數被調用時分配,函數返回時收回分配,稱為自動存儲期限;如果聲明時加上static則不會回收,稱為靜態存儲期限;
8、局部變量的作用域只在本函數內,想要一個全局的變量則需要將變量聲明在函數外,即main函數中;靜態局部變量雖然能一直保持,但也只對本函數可見,其他函數是不可使用的;

六、指針

1、指針變量可以和其他變量一起出現在聲明中;一個指針變量甚至可以指向另一個指針,即指向指針的指針。
2、指針變量可以在聲明同時對它進行初始化(int *p = &i), int * 屬於一個整體,用於表示p是一個指針。
3、指針可以指向數組元素,數組元素之間的地址差值就是它們索引值的差;
4、后綴++的優先級高於*;
5、可用數組的名字作為指向數組第一個元素的指針;聲明a是指針就相當於聲明它是數組,編譯器把這兩類聲明看作是完全一樣的;
6、可以把數組名用作指針,但不能給數組名賦新的值,試圖使數組名指向其他地方是錯誤的;
7、用於指針算術運算的整數需要根據指針的類型進行縮放;

七、字符串

1、C語言把字符串字面量作為字符數組來處理;只要保證字符串是以空字符結尾的,任何一維的字符數組都可以用來存儲字符串(但字符串並不要求一定要有空字符);
2、試圖改變字符串字面量會導致未定義的行為;
3、字符串變量的聲明中可以省略它的長度;
4、轉換說明%s允許printf函數寫字符串。其實也可以用printf(str)來打印字符串,但如果str中含有%則會使printf認為是轉換說明的開始;%.ps可以指定顯示的字符數量為p,%ms會在大小為m的字段內顯示字符串,對於超過m個字符的不會被截斷,而會顯示整個字符串,如果不足m個則會右對齊輸出,如要左對齊則可以在m前加一個減號;
5、put(str)顯示字符串函數;gets(str)讀取字符串,它在開始讀取字符串之前跳過空白字符(scranf函數會跳過),gets函數會持續讀入直到找到換行符才停止(scanf會在任意空白符處停止);
6、在scanf函數中讀取字符串不需要對變量名前加&取址,因為字符串變量名本身就是指針;可用%ns來指定字符串可存儲的最大數量,這樣更安全;
7、getchar()讀取單個字符,且會把它讀取到的字符作為int類型的值返回;
8、字符串的復制,直接讓一個字符串變量名等於另一個字符串或字符串變量名是錯誤的,必須進行逐個的賦值;
或調用函數strcpy(str1,str2),且它會返回str2的值;
strncpy(str1,str2,sizeof(str1)-1)也是字符串的復制,它可以指定從str2復制出字符數量的最大長度;
9、strlen(str) 求字符串的長度;
strcat(str1,str2) 字符串的拼接;
strcmp(str1,str2) 字符串的比較,返回一個小於、等於或大於0的值;
10、相鄰的字符串面量會被合並;

八、預處理指令

1、預處理器是一個小軟件,處理預處理指令;
2、預處理指令都是以#號開始,但並不需要一定在一行的行首,只要#前有空白字符就行,指令的符咒之間可以插入任意數量的空格或水平制表符;
3、指令總是在第一個換行符處結束,且可以出現在程序的任何地方;
4、指令主要有三種類型:宏定義(#define,#undef)、文件包含(#include)、條件編譯(#if,#ifdef,...)
5、簡單的宏格式:#define 標識符 替換列表
功能即用標識符來代替替換列表的內容,替換列表可以包括:標識符、關鍵字、數值常量、字符常量、字符串字面量、操作符、排列;(#define N 100; 是錯誤的,它將N定義為100和;兩個記號);
6、用#define來命名的優點:1)程序更易讀;2)程序更易修改;3)可以幫助避免前后不一致或鍵盤輸入錯誤;4)可以對C語法做小的修改;5)對類型重命名;6)控制條件編譯(#define DEBUG 會將程序在“調試模式”下進行編譯);
7、帶參數宏,格式: #define 標識符(a,b,c,...) 替換列表
宏的名字和左括號之間必須沒有空格。
帶參數宏常用來作為簡單的函數使用;
帶參數的宏可以包含空的參數列表;
8、使用帶參數宏替代真正的函數的優點:
程序可能會稍微快一點;宏更通用,使用范圍更廣;
缺點:
宏參數沒有類型檢查;無法用一個指針來指向一個宏;宏可能會不止一次地計算它的參數(所以應盡量避免使用帶有自增等副作用的參數)
9、宏的替換列表可以包含對其他宏的調用;宏的作用范圍通常到出現這個宏的文件末尾,因為宏不受函數作用域的影響;宏不可以被定義兩遍,可以用#undef指令來取消對一個宏的定義(如果取消一個沒有被定義的宏則不會有任何效果,也不會報錯);
10、對於較長的宏可以是使它們包含在一個圓括號內,表達式之間用逗號分隔;或者使它們包含在一個花括號內,語句間用分號分隔,即一個復合語句,且最好使用do...while循環,while條件為0,且最后不要加分號“;”。
11、#號還有一個作用就是使后邊的記號轉換為字符串,如果包含/號和"號等時會在轉換成字符串時自動添加轉義字符;
12、##運算符的作用是把兩個記號“粘合”在一起,使它們成為一個記號; 如果一個操作數是宏參數,“粘合”會在形式參數被相應的實際參數被替換后發生;
13、C語言預定義宏:
__LINE__ 被編譯的文件中的行號;
__FILE__ 被編譯的文件名;
__DATE__ 編譯的日期(格式為:mm dd yyyy)
__TIME__ 編譯的時間(格式為:hh:mm:ss)
__STDC__ 如果編譯器符合C標准,那么值為1
14、條件編譯 #if...#endif
邏輯同if,效果是如果條件成立則之間的代碼會被編譯進程序,如果不成立則不會被編譯進程序;常用於調試與非調試代碼的區別,還有就是不同平台之間代碼的區別; 還可以用於臨時屏蔽包含注釋的代碼;
15、defined(標識符) 用於判斷一個標識符是否是一個定義過的宏,如果是則返回1,否則返回0
16、#ifdef...#endif 同 #if defined(標識符)...#endif
17、#ifndef...#enif 同 #if !defined(標識符)...#endif
18、#error 常和#if...#endif一起使用,用於向編譯器拋出錯誤;
19、#line 用於改變程序行編號方式,可指定從n號后增加,也可來源一個文件的編號方式;
20、宏可以被遞歸調用,但是不會無限遞歸,只會調用一次后就停止調用了;


其他補充:
共享變量,可以在頭文件對變量進行聲明和定義,在其他文件中用extern type name的方式進行聲明,這樣編譯器不會在編譯這些文件時為變量分配額外的內存空間;但是同一個變量的聲明出現在不同文件中時,編譯器無法檢查聲明是否和變量定義相匹配。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM