C语言深度剖析书籍学习记录 第一章 关键字
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                C语言深度剖析书籍学习记录 第一章 关键字
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                C語言標準定義了32個關鍵字
union聲明聯合數據類型
- Union declaration - cppreference.com
 - 維護足夠的空間來置放多個數據成員中的“一種”,而不是為每一個數據成員配置空間,在 union 中所有的數據成員共用一個空間,同一時間只能儲存其中一個數據成員,所有的數據成員具有相同的起始地址
 
- 一個 union 只配置一個足夠大的空間以來容納最大長度的數據成員,以上例而言,最大 長度是 double 型態,所以 StateMachine 的空間大小就是 double 數據類型的大小。
 - union主要目的是為了壓縮數據存儲的空間,如果變量不會在同一時間被使用到就可以使用 union?
 
enum聲明枚舉類型
- Enumeration declaration - cppreference.com?
 
rigister 聲明寄存器變量
- Storage class specifiers - cppreference.com
 - https://en.wikibooks.org/wiki/C%2B%2B_Programming/Programming_Languages/C%2B%2B/Code/Keywords/register
 - 這個關鍵字請求編譯器盡可能的將變量存在 CPU 內部寄存器中而不是通過內存尋址訪問以提高效率。注意是盡可能,不是絕對。因為 CPU 的寄存器有限
 - 注意: 寄存器在 c 和 c++之間有不同的語義。在 c 語言中,可以通過聲明數組寄存器來禁止數組到指針的轉換: register int a [1] ;?
 - 從 C++ 17 開始,auto 關鍵字不再是 C++ 存儲類說明符,且 register 關鍵字被棄用
 - 這意味著變量的最大尺寸等于寄存器的大小(通常是一個詞),且不能對它應用一元的 '&' 運算符(因為它沒有內存位置)。
 - 存儲空間分配不同,auto類型分配在棧上,屬于動態存儲類別,占動態存儲區空間,函數調用結束后自動釋放;
 - 而static分配在靜態存儲區,在程序整個運行期間都不釋放。兩者之間的作用域相同,但生存期不同
 - static局部變量在所處模塊的初次運行時進行初始化工作,且只初始化一次。
 - 對于局部靜態變量,如果不賦初值,編譯期會自動賦初值0或空字符;而auto類型的初值是不確定的。(對于C++中的class對象例外,class的對象實例如果不初始化,則會自動調用默認構造函數,不管是否是static類型)?
 - register 變量必須是 能被 CPU 寄存器所接受的類型。意味著 register 變量必須是一個單個的值,并且其長度應小 于或等于整型的長度
 
volatile說明變量類型可以被隱含改變
- cv (const and volatile) type qualifiers - cppreference.com
 - 編 譯器對訪問該變量的代碼就不再進行優化,從而可以提供對特殊地址的穩定訪問
 - const volatile修飾的變量 - Jeremy's blog
 
- 這時候編譯器對代碼進行優化,因為在(1)、(2)兩條語句中,i 沒有被用作左值。這時候 編譯器認為 i 的值沒有發生改變,所以在(1)語句時從內存中取出 i 的值賦給 j 之后,這個 值并沒有被丟掉,而是在(2)語句時繼續用這個值給 k 賦值。編譯器不會生成出匯編代碼 重新從內存里取 i 的值,這樣提高了效率。但要注意:(1)、(2)語句之間 i 沒有被用作左 值才行。
 
- ?volatile 關鍵字告訴編譯器 i 是隨時可能發生變化的,每次使用它的時候必須從內存中取出 i 的值,因而編譯器生成的匯編代碼會重新從 i 的地址處讀取數據放在 k 中。這樣看來,如果 i 是一個寄存器變量或者表示一個端口數據或者是多個線程的共享數 據,就容易出錯,所以說 volatile 可以保證對特殊地址的穩定訪問。
但是注意:在 VC++6.0 中,一般 Debug 模式沒有進行代碼優化,所以這個關鍵字的作 用有可能看不出來。你可以同時生成 Debug 版和 Release 版的程序做個測試。 
mutable 存儲類
- mutable?說明符僅適用于類的對象,這將在本教程的最后進行講解。它允許對象的成員替代常量。也就是說,mutable 成員可以通過 const 成員函數修改。
 
thread_local 存儲類
- 使用 thread_local 說明符聲明的變量僅可在它在其上創建的線程上訪問。 變量在創建線程時創建,并在銷毀線程時銷毀。 每個線程都有其自己的變量副本。
 - thread_local 說明符可以與 static 或 extern 合并。
 - 可以將 thread_local 僅應用于數據聲明和定義,thread_local 不能用于函數聲明或定義。
 - 以下演示了可以被聲明為 thread_local 的變量:
 
定義
- 所謂的定義就是(編譯器)創建一個對象,為這個對象分配一塊內存,取上一個名字,這個名字就是變量名或對象名。
 - 但注意,這個名字一旦和 這塊內存匹配起來,它們就同 生共死,終生不離不棄。并且這塊內存的位置也不能被改變。
 - 一個變量或對象在一定的區 域內(比如函數內,全局等)只能被定義一次,如果定義多次,編譯器會提示你重復定義 同一個變量或對象。
 
聲明? 兩重含義
第一重
- 通知編譯器,變量名字 已經匹配到一塊內存空間,此刻出現的變量或對象是在別的地方已經定義過了
 - 聲明可以出現多次
 
第二重
- 通知編譯器,名字已經提前預定了,別的地方再也不能用它來作為變量名或對象名
 - 例子:void fun(int i, char c);
 
例子
- int i; 定義
 -  
extern int i; 聲明
 
重點:
- 定義聲明最重要的區別:定義創建了對象并為這個對象分配了內存,聲明沒有分配內存
 
基本數據類型
- 使用sizeof 查看具體平臺數據類型的大小
 
命名規則
- ?所有宏定義、枚舉常數、只讀變量全用大寫字母命名,用下劃線分割單詞。?
 
- 定義變量的同時千萬千萬別忘了初始化。因為,定義變量時編譯器并不一定清空了 這塊內存,它的值可能是無效的數據
 - 不同類型數據之間的運算要注意精度擴展問題,一般低精度數據將向高精度 數據擴展。
 
sizeof
- sizeof(p) 和 sizeof(*p)的區別?
 - sizeof(p)是指針類型,64位平臺是8,32位平臺是4
 - sizeof(*p) 是指針指向的數據類型的大小,如果是long double就是16,double是8,int 是4
 
- for 循環內,當 i 的值為 0 時,a[0]的值為-1。關鍵就是-1 在內存里面如何存儲。
 - 計算機系統中,數值一律用補碼來表示(存儲)。主要原因是使用補碼,可以將符號位和其它位統一處理;同時,減法也可按加法來處理。另外,兩個用補碼表示的數 相加時,如果最高位(符號位)有進位,則進位被舍棄。正數的補碼與其原碼一致;負數的 補碼:符號位為 1,其余位為該數絕對值的原碼按位取反,然后整個數加 1。
按照負數補碼的規則,可以知道-1 的補碼為 0xff,-2 的補碼為 0xfe......當 i 的值為 127 時,a[127]的值為-128,而-128 是 char 類型數據能表示的最小的負數。當 i 繼續增加,a[128] 的值肯定不能是-129。因為這時候發生了溢出,-129 需要 9 位才能存儲下來,而 char 類型 數據只有 8 位,所以最高位被丟棄。剩下的 8 位是原來 9 位補碼的低 8 位的值,即 0x7f。 當 i 繼續增加到 255 的時候,-256 的補碼的低 8 位為 0。然后當 i 增加到 256 時,-257 的補 碼的低 8 位全為 1,即低八位的補碼為 0xff,如此又開始一輪新的循環...... - 按照上面的分析,a[0]到 a[254]里面的值都不為 0,而 a[255]的值為 0。strlen 函數是計 算字符串長度的,并不包含字符串最后的‘\0’。而判斷一個字符串是否結束的標志就是看 是否遇到‘\0’。如果遇到‘\0’,則認為本字符串結束。分析到這里,strlen(a)的值為 255 應該完全能理解了。這個問題的關鍵就是要明白 char 類型默認情況下是有符號的,其表示的值的范圍為[-128,127],超出這個范圍的值會產生溢 出。另外還要清楚的就是負數的補碼怎么表示。弄明白了這兩點,這個問題其實就很簡單了。
 
switch case
- case 后面只能是整型或字符型的常量或常量表達式(想想字符型數據在內存里 是怎么存的)?
 - switch case排列順序 
- 把正常情況放在前面,而把異常情況放在后面
 - 按執行頻率排列 case 語句
 
 - switch 里面不可以使用 continue?
 - ?在switch case 語句中能否使用continue關鍵字?_Keep Fighting All The Time-CSDN博客_switch語句中的continue
 
循環代碼
- 多重循環中,如果有可能,應當將最長的循環放在最內層,最短的循環放在最外層,以減少 CPU 跨切循環層的次數。
 
void
- void *可以指向任何類型的數據?
 -  
void 不能代表一個真實的變量,因為沒有內存空間
 
return關鍵字
- c++ - Return char* from function - Stack Overflow
 
return char*
- 函數內新建一個static char數組,這樣函數結束數組也不會被銷毀? ?/? ?使用const char * 字符串存儲在常量區
 - 函數內部動態申請內存,使用完需要釋放內存
 - 全局聲明數組,不好,別人會改
 - 函數返回char* 的解決方案_芒果兒-CSDN博客_c++ 返回char*
 
const
- case 語句后必須是一個常量,const 修飾的只讀變量仍然是變量,所以是不可以的
 - 【C語言】const關鍵字用法 - 代碼先鋒網
 
- const 定義的只讀變量從匯編的角度來看,只是給出了對應的內存地址,而不是象#define 一樣給出的是立即數,所以,const 定義的只讀變量在程序運行過程中只有一份拷貝(因為 它是全局的只讀變量,存放在靜態區),
 - 而#define 定義的宏常量在內存中有若干個拷貝。 #define 宏是在預編譯階段進行替換,而 const 修飾的只讀變量是在編譯的時候確定其值。
 - #define 宏沒有類型,而 const 修飾的只讀變量具有特定的類型。?
 
- const 離哪個近,修飾哪個變量,不可以改變?
 
- 修飾函數的參數? 告訴編譯器 ,形參輸入,在函數體中的不能改變,從而防止了使用者的一些無意的或錯誤的修改。?
 - 修飾函數的返回值 const 修飾符也可以修飾函數的返回值,返回值不可被改變。例如: const int Fun (void);
 
參考鏈接
- What does sizeof (int) * p semantically mean?
 - c - Difference between sizeof(*p) and sizeof(p)? - Stack Overflow
 - c語言中的 %u 什么意思啊?_百度知道
 
struct關鍵字
- 多種數據組合起來的一個整體,其表現形式是一個結構體
 - 傳入傳出都是結構體的形式,可以壓縮傳輸的參數
 - 結構體所占的內存大小是其成員所占內存之和? sizeof(struct),這里還涉及到結構體的內存對齊
 - 即使是空的結構體,使用sizeof求內存,其大小是1,主要是為其分配一個地址,空類也是一樣的
 
柔性數組
- 結構中的最后一個元素允許是未知大小的數組,這就叫做柔性數組成員,但結構中的柔性數組成員前面必須至少一個其他成員。
 - 柔性數組成員允許結構中包含一個大小可變的數組。sizeof 返回的這種結構大小不包括柔性數組的內存。包含柔性數組成員的結構用 malloc ()函數進行內存的動態分配,并且分配的內存應該大于結構的大小,以適應柔性數組的預期大小。
 - 用 sizeof(type_a)得到的只有 4,就是 sizeof(i)=sizeof(int)。那個 0 個元素的數組沒有占用空間,而后我們可以進行變長操作了。使用malloc分配內存之后,使用sizeof探測整體的數據大小,仍然是 4
 - 柔性數組只是編外人員,不占結構體的編制。只是說 在使用柔性數組時需要把它當作結構體的一個成員,僅此而已。再說白點,柔性數組其實與 結構體沒什么關系,只是“掛羊頭賣狗肉”而已,算不得結構體的正式成員
 - 當然,上面既然用 malloc 函數分配了內存,肯定就需要用 free 函數來釋放內存
 - 這個柔性數組的概念 實際使用很少
 
?大端模式 和 小端模式
- 大端模式(Big_endian):字數據的高字節存儲在低地址中,而字數據的低字節則存放在高地址中。
 - 小端模式(Little_endian):字數據的高字節存儲在高地址中,而字數據的低字節則存放在低地址中。
 
?
- 變量i占4個字節,但只有一個字節的值為1,另外三個字節的值都為0。如果取出低地址上的值為0,毫無疑問,這是大端模式;如果取出低地址上的值為1,毫無疑問,這是小端模式。
 
使用程序驗證
#include <iostream> #include <cstring>int checkSystem(){union check{int i;char ch;}c;c.i = 1;return (c.ch == 1); } int main(){int a = checkSystem();std::cout << a << std::endl; }直接查看內存
?
- ?枚舉變量的大小,實質是常數所占內存空間的大小(常數為int類型,當前主流的編譯器中一般是32位機器和64位機器中int型都是4個字節),枚舉類型所占內存大小也是這樣。參考鏈接:enum枚舉變量所占內存大小_bulebin的博客-CSDN博客_枚舉類型大小
 
?
總結
以上是生活随笔為你收集整理的C语言深度剖析书籍学习记录 第一章 关键字的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: guido python正式发布年份_P
 - 下一篇: GTX 1080新年特价4799元!每周