第七章: 分支控制java
1.while((c=getchar()) != '' && c!= '\n'): 循環讀入字符,直到出現第一個空格或者換行符 while(getchar()!='\n') continue 跳過輸入行的剩餘部分。程序員
2.邏輯表達式是從左到右求值的,一旦發現有使表達式爲假的因素,當即中止求值(這點和java是不一樣的)。好比,if(number !=0 && 12/number ==2),c語言能夠保證右邊不會出現除0錯誤。編程
3.&&和||運算符是序列的分界點。好比while(x++<10 && x+y<20), 在對右邊表達式求值以前,先把x的值增長1.數組
4.用&&來測試範圍,好比 if(range>=90 && range <=100), 不要用if(90 <= range <= 100),這種寫法沒有語法錯誤,可是有語義錯誤,由於編譯器會解釋爲(90 <= range) <= 100, 因此最終值老是爲真。ide
5.控制合法輸入,讀入一個數據,while(scanf("%d",&d)==1),判斷兩個輸入:while(scanf("%f","%f",&length,&width) == 2)函數
6.break 語句實際上是switch語句的附屬物測試
第八章:字符輸入輸出spa
1.緩衝分爲兩類:指針
徹底緩衝:緩衝區滿時被清空,一般用於文件傳輸中,緩衝區塊的大小取決於系統rest
行緩衝: 遇到一個換行字符時將清空緩衝區。鍵盤輸入是標準的行緩衝,所以按下回車鍵將清空緩衝區。
2.如今的某些文件可能還會以 「Ctrl+z」來標記文件結束,也可能沒有(^z)。第二種方式是存儲文件的大小信息。
3.在大多數的Unix系統中,在一行的開始鍵入Ctrl+D會致使傳送文件尾信號,能夠用以下的方式:#include<stdio.h> while((ch=gechar()) != EOF)
4.令程序與文件一同工做有兩種方式:一:明確的使用打開文件等專門的函數 二:重定向:將stdin流(一般是從鍵盤輸入)從新分配至文件。輸入重定向能使用文件代替鍵盤做爲輸入,輸出重定向可使程序用文件代替屏幕做爲輸出。
5. < 是Unix,Linux和Dos的重定向運算符。如 a.out < words, 該運算符把words文件與stdin流關聯起來,將該文件的內容引導至a.out程序,因爲C 將文件和I/O設備至於相同的地位,因此這個文件如今就是I/O設備。
6.使用重定向運算符>和<時,輸入不能來自一個以上的文件,輸出也不能定向至一個以上的文件
7.其它的運算符: (>>) 使得能夠向一個文件的末尾追加數據;管道運算符 (|)能夠將第一個程序的輸出與第二個程序的輸入鏈接起來
8.getchar()讀取每一個字符,包括空格,製表符和換行符,scanf()再讀取數字式則跳過空格,製表符和換行符。putchar()
9.若是混合使用scanf()和getchar()函數,那麼當調用getchar()以前scanf()剛好再輸入緩衝中留下一個換行符,所以會產生問題,可是當咱們知道了這個問題,能夠經過編程手段來避免。
第九章:函數
1.一個函數一般包括三部分:函數原型,告知編譯器函數的類型,函數調用,致使函數的執行,函數定義,確切的制定了函數的具體功能
2.在程序中能夠把函數原型放在main()以前,也能夠放到main()之中,能夠放到變量聲明的任何位置,這兩種方法都是正確的。
3.在函數原型中能夠根據您本身的喜愛省略變量名,如 void show(char, int)
4.被調用函數使用的值是從調用函數中複製而來的,因此無論在被調用函數中對複製數值進行什麼操做,調用函數中的原數值不會收到任何影響。
第十章:數組和指針
1.有關數組初始化:int no_data[size]: 若是不進行數組初始化,則和未初始化的普通變量同樣,其中存儲的是無用的數值;int some_date[4]={1492,1066},若是部分初始化,則編譯器作的很好,多餘的數組元素被初始化爲0. int some_data[4]={1,2,3,4,5,6},這種初始化列表中項目的個數大於數組的大小,編譯器會絕不留情的認爲這是一個錯誤,可是能夠用省略括號中的數字的方式來讓編譯器自動匹配數組大小。int some_data[]={1,2,3,4,5,6}。C99加入了一個新的特性:int days[MONTHS]={32,28,[4]=31,30,31,[1]=29}.有兩點須要說明:1.[4]=31,30,31代表不只days[4]=31,並且days[5]=30,days[6]=31. 2.後面的指定會覆蓋前面的指定。
2.爲何C不檢查數組邊界? 在程序運行前,索引的值可能還沒有肯定下來,因此編譯器此時不能找出全部的索引錯誤。爲保證程序的正確性,編譯器必須在運行時添加檢查每一個索引是否合法的代碼,這回致使程序的運行速度減慢。
3.對於二維數組的初始化,也能夠省略內部的花括號,只保留最外面的一對花括號,在初始化時,按照前後順序來逐行賦值,所以前面的元素首先獲得賦值,直到沒有數值爲止。
4.爲何在聲明指針的時候必須指明指針指向的數據類型?在C中,對一個指針加1的結果是對該指針增長一個存儲單元。對於數組而言,地址會增長到下一個元素的地址,而不是下一個字節。這就是爲何在聲明指針時必須聲明它所指向對象的類型。計算機須要知道存儲對象所用的字節數,因此只有地址信息是不夠的。
5.在函數原型中,因爲名稱能夠省略,則下面四種原型是等價的:
a) int sum(int *ar, int n)
b) int sum(int *, int)
c) int sum(int ar[], int n)
d) int sum(int [], int)
在定義函數時,名稱是不能夠省略的,所以在定義函數時如下兩種方式等價:
a) int sum(int *ar, int n)
{
//code
}
b) int sum (int ar[], int n)
{
//code
}
其中,有一點提出的是, 在函數原型和函數定義這兩種場合中, int* ar 和 int ar[]是等價的。
6. c中數組和指針的關係容許您在數組符號中使用指針ar。
int sum(int *ar, int n)
{
ar[i] = ...
}
但在這種狀況下,sizeof ar 爲 4. 即便爲
int sum(int ar[], int n)
{
}
這種狀況下sizeof ar 任然爲4.
然而,若是在定義的區域內查看sizeof,如:
int marbles[10] = {1,2,3,4,5,6,7,8,9,10}
printf("The size of marbles is %zd bytes.\n.", sizeof marbles);
這種狀況下,會輸出40.(10 * 4)
第12章:存儲類,連接和內存管理
1.文件做用域變量有時也被稱爲全局變量。
2.一個C變量具備下列連接之一:外部連接(external linkage)(static), 內部連接,或空連接。具備代碼塊做用域或者函數原型做用域的變量具備空連接,覺得着他們是由其定義所在的代碼塊或函數原型所私有的。具備文件做用域的變量可能有內部或者外部連接。一個具備外部連接的變量能夠再一個多文件程序的任何地方使用。一個具備內部連接的變量能夠在一個文件的任何地方使用。
3.在內層代碼塊中定義的名字是內層代碼塊所使用的變量,咱們稱之爲內層定義覆蓋(hide)了外部定義,但當運行離開內層代碼塊時,外部變量從新恢復做用。
4.可能須要 -std=C99來激活編譯器的C99支持。
5.在C中,除非顯示地初始化自動變量,不然它不會被自動初始化。
6. void trystat() {
int fade = 1;
static int stay = 1;
}
這兩個聲明看起來很類似,可是第一個語句確實是函數trystat()的一部分,每次調用該函數都會執行它,它是個運行時動做,而第二個語句實際上並非函數的一部分。靜態變量和外部變量在程序調入內存時已經就位了,把這個語句放在函數內部是爲了告訴編譯器只有函數trystat()能夠看到該變量,它不是在運行時執行的語句。
7. 外部變量
1)把變量的定義聲明放在全部函數以外,即建立了一個外部變量。
2)在使用外部變量的函數中經過使用extern關鍵字來再次聲明它
3)若是變量實在別的文件中定義的(而不只僅是在文件頭部定義的話),使用extern來聲明一下該變量就是必須的。
8. 定義和聲明的區別
int tern = 1;
main()
{
external int tern;
...
}
這裏tern聲明瞭兩次。第一次聲明爲變量留出了存儲空間,構成了變量的定義,稱爲定義聲明
第二次聲明只是告訴編譯器要使用先前定義的變量tern,所以不是一個定義,爲引用聲明,關鍵字extern代表該聲明不是一個定義。
9. 一個外部變量只能夠進行一次初始化,並且必定是在變量被定義時進行。下面的語句是錯誤的
extern char permis = 'Y';
10.具備內部連接的靜態變量
普通的外部變量能夠被程序的任一文件所包含的程序使用,而具備內部連接的靜態變量只能夠被與它在同一個文件中的函數使用。能夠在函數中使用存儲類說明符extern來再次聲明任何具備文件做用域的變量。這樣的聲明並不改變連接。
11.除了一個定義聲明外,其餘全部聲明都必須使用關鍵字extern,而且只有在定義聲明中才能夠對該變量進行初始化。
12. 函數能夠是外部的,靜態的或者內聯的。與變量相似。
12.將頭文件文件名置於雙引號而不是非尖括號中,是爲了只是編譯器在本地尋找文件,而不是到編譯器存放標準頭文件的標準位置去尋找文件。一些常見的作法是將頭文件與源代碼文件放在同一個目錄或文件夾中,或者與工程文件放在同一個目錄或文件夾中。
13.stdlib.h裏包括的函數原型:rand(), malloc(),free(),exit()
14.free()只釋放它的參數所指向的內存塊,若是free()在一個程序的最後而後立刻退出的話,沒有free()也能夠,由於在程序終止後全部已經分配的內存都將會被自動釋放。
15.一個理想模型:程序將它的可用內存分爲三個獨立的部分:一個是具備外部連接的,具備內部連接的以及具備空連接的靜態變量的部分;一個是自動變量的部分;一個是動態分配的內存的部分:
1)在編譯時就已經知道了靜態存儲時期存儲類變量所需的內存數量,存儲在這一部分的數據在整個程序運行時均可用。這一類型的每一個變量在程序開始時就已存在,到程序結束時終止。
2)一個自動變量在程序進入包含該變量定義的代碼塊時產生,在退出這一代碼塊時終止。所以,伴隨程序對函數的調用和終止,自動變量使用的內存數量也在增長和減小。典型的,將這一部份內存處理爲一個堆棧。這意味在內存中,新變量在建立時按順序加入,在消亡時按相反順序移除。
3)動態分配的內存在調用malloc()或相關函數時產生,在調用free()時釋放。由程序員而不是一系列固定的規則控制內存持續時間,所以內存塊能夠在一個函數中建立,而在另外一個函數中釋放。因爲這點,動態內存分配所用的內存部分可能變成碎片狀,也就是說,在活動的內存塊之間散佈着未使用的字節片。無論怎樣,使用動態內存每每致使進程比使用堆棧慢。
16. restrict關鍵字告訴編譯器某個指針是訪問它所指向數據塊的惟一初始方式,編譯器能夠放心去尋找計算的捷徑。好比合並兩次加法。
17. 從宏變成最終的替換文本的過程稱爲宏展開
18. C編譯器在編譯時對全部常量表達式(只包含常量的表達式)求值,因此實際相乘過程發生在編譯階段,而不是預處理階段。預處理器不進行計算,他只是按照指令進行文字替換操做。
19.對於#include。 使用雙引號意味着首先搜索本地目錄,可是具體搜索那個目錄依賴於編譯器,有些編譯器搜索源代碼文件所在目錄,有些則搜索當前工做目錄,