1 只在頭文件中作聲明
2. 補碼是負數真正的物理存儲格式
3. double f2 = 1.0;
printf("%lf", f2);
long double f3 = 1.0;
printf("%Lf", f3); // 注意下,長雙精度不是 %llf
,而是 %Lf
4. 字符9和數字9。字符9存儲的是ascii碼,數字9存儲的是9的二進制表達式。
5. 循環條件是 getchar() != '\n'
,這句話的意思是,用getchar()
這個函數去緩沖區拿取數據,每次去拿一個字符,只要不是回車符 '\n'
,就繼續循環,直到拿到回車符為止。為什麼是回車符呢?因為用戶再輸入的時候,最後一定是按了一下回車鍵來結束輸入的(本質原因是標准輸入流是行緩沖類型的),因此在緩沖區中的數據一定是以回車符
'\n' 作為結尾的,當我們用 getchar()
獲取到回車符時,就表示緩沖區就被我們清空了!
6. 位運算符
7. Switch中表達式的值必須是整型
8. Goto語句,在linux內核中常出現在跳轉錯誤處理的代碼中
9. 內聯函數就是典型的用空間換取時間的例子
10. 回調函數
11. 函數指針有兩種用法,第一是在結構體中實現面向對象,實際就是用函數指針指向操作結構體數據的函數。
signal(SIGINT, func); // 捕捉SIGINT,順便告訴內核其響應函數是func,函數名func就是函數指針
這樣,當進程收到SIGINT時,就會進入內核,執行內核的相關動作,然後內核按照用戶層提供的func這個函數指針,回到用戶控件調用func函數,因此這個函數也被稱為回調函數,回調函數實現了不同的程序模塊由不同的人開發,而且又可以協調合作的目的。
20.
extern int a; //聲明一個“別處”定義的全局變量,此處extern不可省略
extern int f(); // 聲明一個“別處”定義的函數,此處extern可省略
“別處”的意思僅僅指不在當前位置,可能是別的文件,也可能是該文件的其他地方。注意,如果聲明的是一個變量,那只能是全局變量,局部變量不能用extern來聲明。
被聲明為register類型的變量一般是因為程序對其讀寫性能很敏感,比如在底層操作系統中,要頻繁地對某個變量進行讀寫,而且這個變量的讀寫速度直接影響到了程序的性能,是整個程序的熱點也是瓶頸,那麼就很有必要將其聲明為register存儲型。
auto這個關鍵字就像signed一樣,一般都會被省略。因為auto的含義是將一個變量存儲在“自動”存儲區,所謂的自動存儲區就是進程的棧空間,而普通的局部變量默認就是存儲在棧空間的,所以沒有必要再用auto來修飾。而auto又不能修飾全局變量,因為全局變量一定是存儲在靜態區的。
注意上圖中的用戶棧和運行時堆,它們是會在程序運行時動態變化的,裡面的變量時而誕生時而消亡,具體而言指的是:在棧中存在的變量都是局部變量(包括函數的形參),其生命周期是從定義它的語句開始,到離開其作用域為止。在堆中存在的變量都是所謂的動態內存,這些內存的生命周期都是由程序員指定的,從malloc()分配某塊內存開始,到free()釋放這塊內存結束。堆和棧分別向上和向下的箭頭代表它們在內存中的增長的趨勢。
讀寫段(即靜態區)、代碼段、常量區等內存區域則在程序運行期間是“穩定”的,即不會被釋放,這些區域的內容將會被一直保留,直到整個程序退出為止。
以下情況不適合使用局部變量:
第一,巨大的變量。比如一個2000個元素的數組,那麼大的數據量很有可能使得棧溢出。
第二,動態的數據。比如一個動態增長的鏈表,雖然程序運行初時不大,但是程序無法預料以後該鏈表的節點數目,像這種動態的數據也不能用棧空間來存放。
由於棧空間的分配跟釋放是由系統自動完成的,其執行效率高速度快,所以適合用來存放一些可以被臨時釋放的數據。
而堆空間,則是程序運行時大部分數據的真正的演練場,這部分空間的分配和釋放完全由程序員來控制,因此也叫做內存的自由區,自由意味著謹慎,如果只分配不釋放,內存就會很快被用光,因此,堆空間是一個需要你更加負責任的地方。
動態內存的使用有幾點要注意:
1,使用完畢之後,一定要釋放。
2,如果不釋放,那麼該塊內存只能等到程序全部退出之後才能被釋放。
3,free()
只能釋放動態內存(即由malloc( )
或者 calloc()
或者 realloc()
分配的內存)。
4,訪問動態內存的唯一方式是采用指針,因為動態內存是匿名的。
21.
struct student Jack = {
.name = "Jack",
.score = 88.5,
.age = 20
};
一個有趣的地方是:數組不能這樣直接賦值,但是如果兩個結構體裡面包含數組,結構體卻可以直接賦值。
乍看起來,一個結構體變量的大小,就應該等於其各個成員的大小之和,但事實並非如此,各個成員之間,會常常由於所謂的“地址對齊”的問題而被填充一些零,因此一般來說一個結構體的大小往往要大於其各個成員的大小之和(至少是相等)。
1,如果一個變量的長度 length <= CPU的字長,那麼要求該變量自然對齊。2,如果一個變量的長度 length >= CPU的字長,那麼該變量只要按CPU的字長對齊即可。
而聯合體完全不同,聯合體的所有成員的起始地址都是一樣的,換句話講,它們將來將會相互覆蓋!最後對哪一個成員賦值,哪一個成員就有效,其他的統統失效。結構體的大小計算比較復雜,要考慮地址對齊,聯合體的大小非常簡單,決定於最大成員。