第一章--C語言的基本概念
丹尼斯 里奇
一、什么是C語言?
定義:是一個面向過程的計算機高級語言--不需要任何運行環境便能運行的程序語言;
發展:目前是C11 ( K&R C—>ANSI C / C89標准—>C99標准——>C11標准);
二、什么是C程序?
概念:有很多的函數(小程序段)構成,main函數為主函數-程序執行入口;
C語言執行過程:程序編寫出來通過(編譯器)編譯連接后生成機器語言,計算機才可以執行。目前用的Clang編譯器是作者: 克里斯·拉特納(英語:Chris Lattner,1978年)
第二章--基本語法
(關鍵字、標識符、數據、注釋、常量、變量、printf/scanf、函數、進制)
一、什么是關鍵字?
概念:C語言本身提供的具有特殊功能的字符 (共32個);
注意:全都是小寫字母,系統會自動高亮;
1-----------------------數據類型關鍵字
- int :整型數據,通常為默認類型;
- float :單精度浮點型;
- double :雙精度浮點型;
- char :字符型類型數據,屬於整型數據的一種;
- void :空類型,聲明函數無返回值或無參數,聲明無類型指針,顯式丟棄運算結果 ;
- short :修飾int,短整型數據,可省略被修飾的int;
- long :修飾int,長整形數據,可省略被修飾的int;
- signed :修飾整型數據,有符號數據類型;
- unsigned :修飾整型數據,無符號數據類型;
- struct :結構體聲明;
- union :共用體聲明;
- enum :枚舉聲明;
- typedef :聲明類型別名;
- sizeof :得到特定類型或特定類型變量的大小;
- auto :指定為自動變量,由編譯器自動分配及釋放。通常在棧上分配
- static :指定為靜態變量,分配在靜態變量區,修飾函數時,指定函數作用域為文件內部
- register :指定為寄存器變量,建議編譯器將變量存儲到寄存器中使用,也可以修飾函數形參,建議編譯器通過寄存器而不是堆棧傳遞參數
- extern :指定對應變量為外部變量,即標示變量或者函數的定義在別的文件中,示編譯器遇到此變量和函數時在其他模塊中尋找其定義。
- const :與volatile合稱“cv特性”,指定變量不可被當前線程/進程改變(但有可能被系統或其他線程/進程改變)
- volatile :與const合稱“cv特性”,指定變量的值有可能會被系統或其他進程/線程改變, 強制編譯器每次從內存中取得該變量的值
2-----------------------流程控制關鍵字
- return :用在函數體中,返回特定值(或者是void值,即不返回值)
- continue :結束當前循環,開始下一輪循環
- break :跳出當前循環或switch結構
- goto :無條件跳轉語句
- if :條件語句,后面不需要放分號
- else :條件語句否定分支(與if連用)
- switch :開關語句(多重分支語句)
- case :開關語句中的分支標記
- default :開關語句中的“其他”分支,可選。
- for:循環結構,for(1;2;3)4;的執行順序為1->2->4->3->2...循環,其中2為循環條件;
- do :do循環結構,do 1 while(2); 的執行順序是1->2->1...循環,2為循環條件;
- while :while循環結構,while(1) 2; 的執行順序是1->2->1...循環,1為循環條件;
二、什么是標示符?
概念:在程序中自定義的一些符號和名稱;由26個英文字母的大小寫、10個阿拉伯數字0~9、下划線_,$組成;
注意:
- 1.不能以數字開頭
- 2不能與關鍵字重名
- 3.嚴格區分大小寫
- 4.起名要有意義
- 5.便於識別(駝峰命名)
三、什么是數據?
概念:在計算機中的存儲形式,由二進制數0和1組成。例如文字、圖片、聲音;
注意:
- 單位:1byte(字節)=8bit 1KB=1024byte 1MB(兆)=1024KB 1G=1024MB 1T=1024G;(最小單位為bit)
- 分為靜態數據和動態數據;
- 靜態數據:硬盤中存儲的內容,長期有效存在;
- 動態數據:系統緩存當中的內容,一旦停電則會消失;
MB與Mb的區別:一般數據機及網絡通訊的傳輸速率都是以「bps」為單位。
大寫 B代表 Byte,小寫 b 代表 bit。如4Mbps 及 10Mbps 等等。以1M 寬帶為例,1Mbps 等如1 X 1024/8,亦即等如128 KB/s
10M 光纖下載速度=1秒鍾可以下載1.28MB(兆)的數據.---理論上
三(1)什么是數據的數據類型?
概念:有五大數據類型。基本類型、構造類型、指針類型、空類型、定義類型;


注意:
- 1整型:用於表示整數,根據表示范圍的不同分為以下三種: 短整型(short) < 整型(int) < 長整型(long);
- 2浮點型:用於表示小數,根據范圍和精度不同分為以下兩種: 單精度浮點數(float) 精度為7位< 雙精度浮點數(double) 精度為16位;
- 3字符型:用來述單個字符,char ;
四、什么是注釋?
概念:對代碼進行解釋說明,輔助調試代碼,不參加編譯
- 單行注釋://想注釋的內容
- 多行注釋:/*想注釋的內容*/
注意:
- 只能在一句完整的代碼后面.不能在前面,或插在中間;
- 多行注釋可以嵌套單行,但是不能嵌套多行;
五、什么是常量?
概念:一些固定不變的量;
注意:數據不會改變!!
- 二進制數: 0b開頭 0b00001010;
- 八進制數: 0開頭 012;
- 十進制數: 默認 10
- 十六進制: 0x 0xff01
- 單精度:2.3f
- 雙精度:4.5 (默認)
- 例如:'a' ,' ', '$', '\n' (轉義字符)
- 例如:"abc", "a", " "(空格), ""(空字符串)
五、什么是變量?
概念:表示一個需要經常改變或者不確定的數據,(變量在內存中代表了一塊內存區域);
使用流程:定義——>初始化——>使用
int a;
int a,b,c;
變量定義后不賦值:這個變量的值是不確定的(1.隨機數 2.上個程序在內存中駐留的3.系統的)
2.變量的初始化
- 1)先定義,后初始化
- 2)定義的的同時初始化
- 3)使用其他的變量初始化
- 4)連續初始化
int a,b,c;
a = b = c =10;
- 1.作用域是其所在位置之下的所有函數,都可以共享並改變.
- 2.變量的使用遵循就近原則如果函數內有同名變量,那么用函數自已的.
- 3.如果沒有初始化賦值,默認值是0;
- 創建一個變量相當於在內存中占用了一塊空間
- 這個空間的大小是固定的,但里面的數據可以改變
- 同一個作用域內不能有相同的變量名.
- 塊的內部可以訪問全局變量
- 在塊的外部不能訪問塊內部的局部變量
- 塊的內部可以定義和全局變量同名的變量(互不干擾)
- 初始化時創建,在函數作用域執行完后失效,且內存空間釋放.
六、什么是printf函數?
概念:標准的輸出函數
輸出的原理 : printf把要輸出的內容--->輸出緩沖區-->輸出到控制台
格式:printf("格式說明",變量列表)
常見的格式說明符:
%d 整型
%c 字符型
%s 字符串型
%f 浮點型
%p 地址
用法:
int a=10;
printf("hello world----%d",a);
七、什么是scanf函數?
概念:C語言中標准的輸入函數 接收用戶從鍵盤上輸入的內容(阻塞式函數-等待用戶的輸入,如果不輸入會一直等待)
格式:scanf("格式控制",地址列表)
---地址怎么來的? ---&-取地址符號
用法:接受數字(單個/多個/數字字符混合型)
int a;
scanf("%d",&a);
八、什么是函數?
概念:組成C語言源程序的基本單位,完成特定功能的代碼段.
main()為主函數:程序入口
優點:對一個功能進行封裝,提高程序可讀性、復用性,提高開發效率;
定義:
返回值類型 函數名(形式參數類型 參數名1,……){
函數體;
//return (返回值)
}
函數定義到使用分三步:1、聲明--->2、定義函數--->3、調用函數。
一共四種類型:
- 有參無返回值:void test(int x,float y){ }
- 無參無返回值:void test1(){ }
- 有參有返回值: int max(int x,int y){ return x>y?x:y; }
- 無參有返回值: int test2(){ return 10;}
1.函數的參數
1)形參和實參
形參:在定義函數的時候,函數名后面小括號中的參數 , 格式: 數據類型 變量 如:int x;
形參的作用域:只能在本函數中使用
實參:調用函數的時候傳遞的參數
max(56,78);
56、78就是兩個實際參數
2)參數的傳遞的過程
2、函數的返回值
概念:執行函數體中的程序段,最后獲取的值並返回給主調函數,函數的返回值只能通過return 關鍵字進行返回
格式:return 表達式;/ return (表達式);
注意:
-
return 0; return (a+b); return a>b?a:b;
-
返回值類型不定義默認是int.如果不需要具體返回值類型用void(return可以省略);
- 返回值類型要與返回值相同;
-
是否要定義形參看是否有未知內容參與運算,調用時實參必須對應.參數傳遞的是值.;
-
函數中可以有多個return ,但是只有一個起作用;
3、函數的調用
1)函數的聲明:
由於程序是由上到下執行,編譯器不知道我們是否已經定義了某個函數,為了防止編譯器編譯的時候報錯(函數調用)所以,要告訴編譯器,我已經定義了哪些函數
- 原則:
在調用函數之前,進行該函數的聲明
- 聲明的方法:
技巧:復制函數的頭部,加上分號,寫在調用調用方法之前
int max(int x,int y); //聲明
max(56,78); //調用
2)函數的調用
定義:函數名(實參列表);
注意:
1)形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。
2)實參可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須具有確定的值 。
3)實參和形參在數量上,類型上,順序上應嚴格一致,否則會發生類型不匹配的錯誤。
4、遞歸函數
概念:在函數中自己調用函數自己
- 能夠進行遞歸的有兩個條件:
1)能夠找到讓問題的規模縮小的規律
2)能夠讓遞歸結束的條件
- 遞歸函數的執行有兩個階段:
1)遞推階段:問題規模縮小的過程
2)回歸迭代:迭代計算值得過程遞歸的
優點和缺點:
- 優點是:遇到問題規模能夠縮小,而且有規律的問題的時候,代碼比較簡潔
- 缺點:消耗內存
- 建議:在程序中不能用太多
進制及內存分析
二進制:0b或者0B開頭 ----逢二進一 0101
八進制:0開頭 ----逢八進一 01234567
十進制:直接寫 ----逢十進一 0123456789
十六進制:0x或0X開頭 ----逢十進一 0-9 A B C D E F (內存的地址格式)
進制的打印輸出:
%o:表示輸出不帶符號八進制整數
%x:表示輸出不帶符號十六進制整數
%d:表示輸出有符號十進制整數
%u:表示輸出不帶符號十進制整數
注意:
- 二進制不可以直接輸出.
- 有符號與無符號區別:有符號可以有負數表現(如: - 2)
進制互換
三個要素:
數位(0-7)、
基數(每一位能取值的個數)、
位權(數碼*基數^數位)、 101 = 1*2^0+0*2^1+1*2^2
數碼(每一位是1還是0)
轉換:有得時候轉換為人能識別的數制,要操作計算機寫計算機能夠識別的語言(二進制)
10 -> 2 : 除2取余法,把10進制數除以2,然后取得余數的序列,再倒序
2 -> 10 : 所有位的位權相加 101 = 1*2^0+0*2^1+1*2^2
2 --> 16 : 4合1法, 整數部分從右向左 4位結合成一位,小數部分從左向右4位結合1位, 不足部分補0
16 -->2: 1拆4法, 16進制的1位拆成二進制的4位
2-->8 8-->2:3合1 :1拆3
8 --> 10 : 8--> 2 --> 10
16 --> 10: 16 -->2 -->10
3、原碼、反碼和補碼
1)機器碼、真值
一個數的二進制的表示 機器碼
把一個數的二進制轉換為10進值得值 真值
2)計算數據的存儲
存儲的時數的補碼 數是有正負性
正數:最高位 用0表示符號位
負數:最高位 用1表示符號位
3)原碼、反碼、補碼:
正數:就是其二進制表示 +100000001
負數:二進制的最高位是1 -1 11111110
反碼:
正數:就是其二進制表示 +100000001
負數:符號位不變,其他位逐位取反 -1 11111110
補碼:
正數:就是其二進制表示 +1 00000001
負數:反碼+1 -1 11111111
注意:補碼的真值不等於原碼的真值的
4、為什么要使用補碼?
主要是位了優化計算機中的減法
5、補碼的深入講解
1-1 = 1+(-1)
數據取值范圍
一.基本數據類型取值范圍---超出取值范圍數據會定義失敗.
內存管理
內存分為5大區域
棧區 -- 存放局部變量
堆區 -- 程序運行過程中,動態分配的內存
BSS區 -- 未初始化的全局變量和靜態變量
數據段 -- 已經初始化的全局變量和靜態變量
代碼段 -- 程序編譯產生的二進制的數據
4、動態內存管理
1) malloc
(void *)malloc(size) //動態的向內存申請連續的size個字節
返回的是新申請的內存空間的首地址
int *p = (int *)malloc(100); //p是在棧區 malloc(100) 在堆區
malloc不會把新申請的空間初始化
memset(p,0,100); //全部初始化為0
2) calloc
calloc 可以向堆區連續申請多個少
長度為指定長度的空間
int *p = (int *)calloc(5,4); //申請5個長度為4的空間 calloc可以把新申請的空間初始化0
注意:判斷一個空間是否申請成功
if(p!=NULL){
//只有申請成功了,才能操作
}
3) realloc
重新改變一塊內存空間的大小 p = (int *)realloc(p,size);
4) free
釋放我們指定的內存空間
free(p); //p是我們新申請的內存單元 free后,p是一個野指針
如果不釋放,造成內存的泄露
位運算
一,是什么?
是直接對整數在內存中的二進制位進行操作的方法(只能操作整形數據)
二,有什么用?
直接通過操作二進制的位來實現運算,高效
三,怎么用?
&與運算:對應兩個二進位均為1時,結果位才為1,否則為0。(有假為假==0)
|或運算:對應的兩個二進位有一個為1時,結果位就為1,否則為0。(有真為真==1)
^ 異或運算:對應的二進位不同時為1,否則為0。(不同為真==1,相同為假==0)
注意:1.相同整數相^的結果是0.2.一個數^另一數兩次結果不變3.整數相^跟順序無關
~ 取反運算:對整數的各二進位進行取反,包括符號位(0變1,1變0,真假互換)
<< 左移:把整數的各二進位全部左移n位,高位丟棄(包括符號位),低位補0。
左移n位其實就是乘以2的n次方(但移動后符號位變化除外,符號位改變則正負改變)
>> 右移:把整數的各二進位全部右移n位,符號位不變。高位的空缺是正數補0;
是負數高位是補0或是補1 取決於編譯系統的規定;右移n位其實就是除以2的n次方