在C語言中,數據類型不僅是固定內存大小的別名,更是創建變量的「模具」。以基本類型為例:char佔1字節、short佔2字節、int佔4字節。當我們宣告char c; short s; int i;時,實際上是在向編譯器申請對應大小的連續存儲空間,並用變量名作為這段空間的別名。理解「變量是一段實際連續存儲空間的別名」這一本質,對於掌握指針、內存佈局至關重要。
C語言變量擁有屬性關鍵字:
register變量不能取地址(&運算符失效)。if適合區間判斷(按片判斷),switch適合離散值匹配。關鍵細節:
else總與最近的if匹配,不可獨立存在。0 == var防止誤寫成賦值;float不可直接比較0,需定義精度EPS。switch的case值必須為整型/字符型,建議按邏輯順序排列,default處理真正的異常情況。if可功能性替代switch,但反之不行;多分支時switch更簡潔。核心差異在於判斷時機:
do-while:先執行後判斷,循環體至少執行一次。while、for:先判斷後執行,可能零次執行;for語法更緊湊,適合已知次數循環。break終止整個循環,continue跳過本次迭代直接進入下一次判斷。特別註意:switch中不能使用continue(僅在循環中有效)。
void變量(無大小、無標尺),但void*是通用指針:作為左值接收任意指針,作為右值賦值需強制轉換。extern "C")。const:修飾變量為「只讀」,本質仍是變量(佔內存,運行時可被指釖修改),主要約束編譯器。遞歸應用於指針:
const int* p; // *p不可變,p可變
int* const p; // p不可變,*p可變
const int* const p; // 兩者皆不可變
口訣:「左數右指」——const在*左邊限制指向數據,在右邊限制指針本身。
volatile:編譯器偽碼警告,強制每次從內存讀取,用於多線程共享變量、硬體寄存器、信號處理器等「未知因素可能修改」的場景。
#define宏常量。typedef為現有類型起別名,不創建新類型,故不能用unsigned/signed擴展。本質區別於#define的文本替換:typedef有語義,受作用域約束;#define純粹預處理替換。
//非註釋,/* */不可嵌套。經典陷阱:x/*p被誤判為註釋開始。\雙重身份:行連接符(預處理階段合併行,後不能有空格)與字符串/字符常量中的轉義符。單引號'a':字符常量,本質是整數(ASCII碼),佔1字節,'a'+1 == 'b'。
雙引號"a":字符串常量,本質是指針(指向以\0結尾的字符數組),佔2字節('a'+\0),"a"+1指向結束符。
編譯器允許字符串賦值給字符變量、字符與字符串比較,但語義錯誤/可笑,嚴禁使用。
||:左至右,遇真短路返回真,全假才假。&&:左至右,遇假短路返回假,全真才真。!:只識別0,!0 == 1,非0值結果為0。a?b:c可作為邏輯載體。左移<<n相當於乘2^n,右移>>n相當於除2^n,效率高於算術運算。
關鍵規則:左移高位丟棄低位補0;右移低位丟棄高位補符號位(算術右移)。
防錯準則:避免位運算、邏輯運算、算術運算混用;必須混用時多加括號明確優先級。
++i+++i+++i此類表達式依賴編譯器「貪心法」詞法分析:從左到右盡可能多讀取字符構成合法Token。實際開發中嚴禁編寫副作用不明的複合表達式。
算術轉換:低向高(char/short → int → unsigned → long → unsigned long → float → double)。
賦值轉換:右值向左值類型轉換。
函數調用/返回:實參/返回表達式向形參/返回類型轉換。
宏:預處理階段文本替換,無調用開銷,但無類型檢查,參數不求值直接替換,易出錯(副作用、優先級、遞歸)。
條件編譯:#if/#else/#endif在預處理期決定編譯哪些代碼,實現:
#ifndef守衛)區別於運行期if-else:條件編譯不生成目標代碼分支,由命令行宏定義控制。
for (int i = 0; ; i++) { // 無限循環
int num;
printf("請輸入整數(0退出):");
scanf("%d", &num);
if (num > 0) printf("%d是正數\n", num);
else if (num < 0) printf("%d是負數\n", num);
else break; // 輸入0退出
}
srand(time(0));
int ran = rand() % 100 + 1;
for (;;) { // 無限循環
int num;
scanf("%d", &num);
if (num < 1 || num > 100) continue;
if (num == ran) break;
else if (num > ran) printf("大了\n");
else printf("小了\n");
}
printf("猜對了\n");
for (int i = 0; i <= 100; i++) {
if (i % 2) continue; // 奇數跳過
printf("%d ", i);
}
// 直角三角形
for (int i = 0; i < 5; i++) {
for (int j = 0; j <= i; j++) printf("*");
printf("\n");
}
// 等腰三角形
for (int i = 0; i < 5; i++) {
for (int j = 0; j <= i * 2; j++) printf("*");
printf("\n");
}
外層控制行數,內層控制每行星號數,printf("\n")在內層結束後換行,是關鍵。