C語言深度解剖讀書筆記1
關鍵字 | 意義 | 關鍵字 | 意義 |
---|---|---|---|
auto | 宣告自動變數,預設時編譯器一般預設為auto | register | 宣告暫存器變數 |
int | 宣告整型變數 | const | 宣告只讀變數 |
double | 宣告雙精度變數 | volatile | 說明變數在程式執行中可被隱含地改變 |
long | 宣告長整型變數 | typedef | 用以給資料型別取別名(當然還有其他作用) |
char | 宣告字元型變數 | extern | 宣告變數是在其他檔案中宣告(也可以看作是引用變數) |
float | 宣告浮點型變數 | return | 子程式返回語句(可以帶引數,也可以不帶引數) |
short | 宣告短整型變數 | void | 宣告函式無返回值或無引數,宣告空型別指標 |
signed | 宣告有符號型別變數 | continue | 結束當前迴圈,開始下一輪迴圈 |
unsigned | 宣告無符號型別變數 | do | 迴圈語句的迴圈體 |
struct | 宣告結構體變數 | while | 迴圈語句的迴圈條件 |
union | 宣告聯合資料型別 | if | 條件語句 |
enum | 宣告列舉型別 | else | 條件語句否定分支(與if連用) |
static | 宣告靜態變數 | for | 一種迴圈語句 |
case | 開關語句分支 | goto | 無條件跳轉語句 |
default | 開關語句中的其他分支 | sizeof | 計算物件所佔記憶體空間大小 |
break | 跳出當前迴圈 | switch | 用於開關語句 |
部分關鍵字說明
register
register變數必須是能被CPU暫存器接受的型別。意味著register變數必須是單一的值,長度<=整型長度,且register變數可能不存放在記憶體中,所以不能用 “&” 來獲取它的地址。
static
作用1:修飾變數。變數又分為區域性變數和全域性變數,但它們都存在記憶體的靜態區。
作用2:修飾函式。函式前加static使得函式成為靜態函式。此處static指對函式的作用域僅限於本檔案。
靜態全域性變數,作用城僅限於變數被定義的檔案中,其他檔案即使用extern宣告也沒法使用它。準確的說:作用城是從定義之處開始,到檔案結尾處結束,在定義之處前面的那些程式碼行也不能使用它。
靜態區域性變數,在函式體裡面定義的,就只能在這個函式裡用了,同一個文件中的其他函式也用不了。由於被static修飾的變數總是存在記憶體的靜態區,所以即使這個函式執行結束,這個靜態變數的值也不會被銷燬,函式下次使用時仍然能用到這個值。
sizeof
sizeof在計算變數所佔空間大小時,括號可以省略,而計算型別(模子)大小時不能省略。且一般情況下,sizeof是在編譯時求值,所以sizeof(i++)不會引起副作用。由於sizeof(i++)與sizeof(i)結果一樣,所以沒必要也不允許寫這樣的程式碼。同樣,sizeof(i=1234); 也不允許,因為 i 的值還是0,沒有改變。
用sizeof計算字串長度時會算上‘\0’。
if、else
bool變數與“零值”的比較:
if語句寫法:
bool bTestFlaf = FALSE ;
// if(bTestFlaf);這種寫法不會引起誤會
// if(!bTestFlaf);
float變數與“零值”的比較:
if語句寫法:
float fTestVal = 0.0;
if((fTestVal >= - EPSINON) && (fTestVal <= - EPSINON) );
//EPSINON為定義好的精度
指標變數與“零值”的比較:
if語句寫法:
int *p = NULL;//定義指標一定要初始化
//if(NULL == p);
//if(NULL != p);
else到底與哪個if配對
else始終與同一括號內最近的未匹配的if語句結合。
使用if語句的其他注意事項
- 先處理正常情況,再處理異常情況。
- 確保if和else子句沒有弄反。
- 賦值運算子不能使用在布林值的表示式上。
- 所有的if-else if結構應該由else子句結束。
case
- case後面只能是整型或字元型的常量或常量表達式。
- case後面的程式碼儘量不要超過20行。
- 不要為了使用case語句而刻意製造一個變數。
- 將default子句只用於檢查真正的預設情況。
void
void的字面意思是“空型別”,void *則為“空型別指標”,void *可以指向任何型別的資料。void 幾乎只有“註釋”和限制程式的作用。但是是可以定義一個void變數。
void真正用:對函式返回的限定;對函式引數的限定。
眾所周知,如果指標P1和P2的型別相同,那麼我們可以直接在P1和P2間互相賦值;如果P1和P2指向不同的資料型別,則必須使用強制型別轉換運算子把賦值運算子右邊指標的型別轉換為左邊指標的型別。例如:
float *p1;
int *p2;
p1 = (float *)p2;
而void * 不同,任何型別的指標都可以直接賦值給它,無需進行強制型別轉換:
void *p1;
int *p2;
p1 = p2;
但這並不意味著,void*也可以無需進行強制型別轉換地賦給其他型別的指標,因為“空型別”可以包容“有型別”,而“有型別”則不能包容“空型別”。
void *p1;
int *p2;
p2 = p1;//編譯出錯
提示“‘=’:cannot convert from ‘void *’ to ‘int *’ "。
void修飾函式返回值和引數
- 如果函式沒有返回值,那麼應將其宣告為void型別。
在C語言中,凡不加返回值型別限定的函式,就會被編譯器作為返回整型值處理。 - 如果函式無引數,那麼應宣告其引數為void。
- 如果函式的引數可以是任意型別指標,那麼應該宣告其引數為void *。
void不能代表一個真實的變數
const
定義const只讀變數,具有不可變性。
- 節省空間,避免不必要的記憶體分配,同時提高效率。
編譯器通常不為普通const分配儲存空間,而是儲存在符號表中,成為編譯
期間的值,沒了儲存與讀記憶體的操作,使之效率很高。
const定義的只讀變數從彙編的角度來看,只是給出了對瘂的記憶體地址。而不
是像#define一樣給出的是立即數,所以,const定義的只讀變數在程式執行過程中只有一份備份(因為它是全域性的只讀變數,存放在靜態區),而# define定義的巨集常量在記憶體中有若千個備份。 #define巨集是在預編譯階段進行替換,而const修飾的只讀變數是在編譯的時候確定其值。#define巨集沒有型別,而const修飾的只變量具有特定的型別。 - 修飾一般變數。
- 修飾陣列。
- 修飾指標。
- 修飾函式的引數。
void Fun(const int *p);
- 修飾函式的返回值。
const int Fun(void);
小知識點
浮點型標準
使用浮點數應遵循已定義好的浮點數標準:
在表示浮點數的各個位元組中,究竟用多少位表示小數部分,多少位表示指數部分,標準C中無具體定義。
ANSI/IEEE標準的基本規定如下所述。
- 兩種基本浮點格式:單精度和雙精度。
- 兩種擴充套件浮點格式:單精度擴充套件和雙精度擴充套件。
- 浮點運算的準確度要求:加、減、乘、除、平方根、餘數、將浮點格式的數舍人為整數值、在不同浮點格式之間轉換、在浮點和整數格式之間轉換以及比較。
- 在十進位制字串和兩種基本浮點格式之-一的二進位制浮點數之間進行轉換的準確度.單- -性和一致性要求。
- 五種型別的IEEE浮點異常,以及用於向用戶指示發生這些型別異常的條件。
五種型別的浮點異常是:無效運算、被零除、上溢、下溢和不精確。 - 四種射入方向:
①向最接近的可表示的值;
② 當有兩個最接近的可表示的值時,首選“偶數”值;
③向負無窮大(向下);
④向正無窮大(向上)以及向0(截斷)。
以0開頭的數字被認為八進位制格式的數
禁止使用八迸制的常數 (0除外,因カ嚴格意義上來講0也是八迸制數) 和八迸制的轉義字元。
在計算機中,任何以0開頭的數字都被認為是八迸制格式的數(當然十六進位制的0x不算)。所以,當我們寫固定長度的數字時,會存在一定的風險。舉例如下:
code[1] = 109;//對應十迸制的109
code[2] = 100;//對應十迸制的100
code[3] = 052;//對應十迸制的42,因為052是以0開頭,以八進位制形式儲存
code[4] = 071;//對應十迸制的57
在轉義字元中後面跟八迸制數,用於表示ASClI碼等於該值的字元,使用時也可能會出現意想不到的錯誤。
code[5] = ‘\109';
/*可能代表兩個字元,‘\10’後面的9因為超出八進位制表示範圍,被看作字元“9”*/
case後不能加const修飾的常量
#include <stdio.h>
int main()
{
int const a = 4;
int m = 0;
scanf("%d",&m);
switch(m)
{
case a:
printf("m = %d\n",a);
break;
default:
printf("m != %d\n",a);
break;
}
return 0;
}
執行報錯
In function ‘main’:
error: case label does not reduce to an integer constant
case a:
在switch case 語句中能否使用continue 關鍵字?
continue語句與break語句使用場合類似,continue語句是不可以在單獨的switch語句中使用,但可以在一個迴圈內的switch語句中使用
-
不能。
-
continue語句一般形式為"continue"。
-
其作用為結束本次迴圈。即跳出迴圈體中下面尚未執行的語句,對於while迴圈,繼續求解迴圈條件。而對於for迴圈程式流程接著求解for語句頭中的第三個部分expression表示式。
-
continue語句的作用是跳過迴圈本中剩餘的語句,併到迴圈末尾。
-
continue語句只用在for、while、do-while等迴圈體中, 常與if條件語句一起使用, 用來加速迴圈。