首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言核心知識問答精選:類型系統、內存模型、IO 機制與運算符優先級完全指南

     編輯:關於C語言

前言

C 語言看似簡單,實則暗藏無數細節陷阱。本文採用「自問自答」模式,精選 10 個高頻核心問題,涵蓋基本類型體系、sizeof 機制、字符編碼、有符號/無符號表示、標準 IO 緩衝、格式化輸出陷阱、運算符優先級記憶法,直擊本質,助你建立精確的 C 語言心智模型。

Q1: C 語言基本類型體系如何劃分?

分類:

  • 整數類型:char、short、int、long、long long (C99);各有 signed/unsigned 變體。
  • 浮點類型:float (單精度)、double (雙精度)、long double (擴展精度)。
  • 字符類型:char、signed char、unsigned char (三種互不相同類型);C11 新增 char16_t, char32_t。
  • 邏輯類型:_Bool (C99),頭文件 <stdbool.h> 定義 bool、true、false。
  • 聚合類型:struct (結構體)、union (共用體)、enum (枚舉)、數組 []。
  • 指針類型:T*、void* (通用指針)、函數指針。
  • 空類型:void (不可實例化,用於函數返回、指針通用)。

Q2: 不同類型在常見 64 位 Linux (LP64) / Windows (LLP64) 下的大小?

類型LP64 (Linux/macOS)LLP64 (Windows)備註
char11標準保證
short22
int44通常 32 位
long84跨平台最大差異點
long long88C99 保證 ≥64 位
float44IEEE 754 單精度
double88IEEE 754 雙精度
指針8864 位地址總線

結構體對齊陷阱:


struct A { char a; char b; int c; };      // sizeof = 8 (a,b + 2填充 + c)
struct B { char a; char b; char d; int c; }; // sizeof = 8 (a,b,d + 1填充 + c)
struct C { char a; char b; int c; char d; }; // sizeof = 12 (a,b + 2填充 + c + d + 3填充)

規則:成員偏移量必須是其類型大小的整數倍;結構體總大小必須是最大成員大小的整數倍。#pragma pack(n) 可調整對齊係數。

Q3: sizeof 是函數還是運算符?

運算符 (關鍵字)。編譯期計算類型/表達式佔用字節數,**不求值表達式** (如 sizeof(i++) 不會執行 i++)。語法:sizeof(type) 需括號,sizeof expr 可省略括號。

Q4: ASCII 碼表本質與速算技巧

  • 7 位編碼,128 個字符 (0~127),高位固定為 0。
  • 速算:2^7 = 128;2^8 = 256 (16×16);2^10 = 1024 (KB);2^16 = 65536 (64K)。
  • 常用字符碼值:'0'=48、'A'=65、'a'=97、'\n'=10、'\r'=13、' '=32、DEL=127。

Q5: signed char vs unsigned char 範圍與記憶法

類型範圍二進制表示 (8位)記憶口訣
signed char-128 ~ 127最高位符號位,補碼表示無符號 0~255,有符號劈半:-128~127 (正數少一個給 0)
unsigned char0 ~ 255純數值位2^8 - 1 = 255

關鍵:char 是否有符號由編譯器決定 (-fsigned-char/-funsigned-char),跨平台代碼**必須顯式指定** signed char 或 unsigned char。

Q6: scanf/printf 參數傳值還是傳址?

  • printf("%d", a):傳**值** (讀取變量內容)。
  • scanf("%d", &a):傳**地址** (寫入變量內存)。
  • 原因:C 語言參數傳值,scanf 需修改變量,必須傳地址;printf 僅讀取,傳值即可。
  • 常見錯誤:scanf("%d", a) (漏 &) → 未定義行為;格式串空格不匹配 (如 "%d %d" 需輸入空格分隔)。

Q7: 無計算器如何進行二進制/十進制轉換?

負數補碼規則:-x = ~x + 1 (按位取反加一)。

  • -1:0xFFFFFFFF (全 1),非 0x80000000。
  • 十六進制轉二進制:每位 4 bit (0~F)。
  • printf("%%d") 輸出字面量 %d (雙百分號轉義)。

Q8: 輸出單字符除 printf("%c", c) 還有什麼?

putchar(c) / fputc(c, stdout)。putchar 通常實現為宏/內聯,開銷更小。注意 char c = 'bc1' 多字符常量實現定義 (通常取低位)。

Q9: scanf 不按回車能無限輸入嗎?緩衝區機制揭秘

  • 不能。標準輸入默認**行緩衝**:用戶輸入字符進內核終端驅動緩衝區,按 Enter (發送 \n) 後,整行數據連同 \n 一起交付給用戶態 stdin 流緩衝區 (通常 4KB)。
  • scanf 從 stdin 緩衝區讀取;緩衝區空則阻塞等待。
  • fflush(stdin) **C 標準未定義行為** (僅 Windows MSVC 支持清空輸入緩衝區)。跨平台清空輸入緩衝區:int c; while((c=getchar())!='\n' && c!=EOF);。
  • 經典坑:scanf("a=%c", &a); scanf("b=%c", &b); 第二次讀到殘留的 \n。解決:格式串加空格 " %c" 跳過空白符,或用 getchar() 吞噬換行。

Q10: 運算符優先級速記口訣 (自高到低)

單目 (++ -- * & ! ~ (type) sizeof) 
→ 算術 (* / % → + -) 
→ 移位 (<< >>) 
→ 關系 (< <= > >=) 
→ 相等 (== !=) 
→ 位與 (&) 
→ 位異或 (^) 
→ 位或 (|) 
→ 邏輯與 (&&) 
→ 邏輯或 (||) 
→ 條件 (?:) 
→ 賦值 (= += -= *= /= %= <<= >>= &= ^= |=) 
→ 逗號 (,)

口訣:「單目最高,算術次之,移位關系邏輯條,賦值最後,逗號最低」。括號 ()、下標 []、成員 . ->、後置 ++ -- 為**後綴運算符**,優先級最高 (結合性左至右)。

結語

C 語言的精髓在於類型系統與內存模型的精確對應。搞清 sizeof 編譯期計算、scanf 地址傳遞、補碼表示、緩衝區行緩衝、運算符優先級結合性,就能規避 90% 的低級 Bug。建議:隨時備查 C99/C11 標準草案 (N1570),養成「不確定就查標準」的習慣。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved