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

C語言學習筆記(一):原碼補碼、編譯流程、類型模型、scanf陷阱與指針效率

     編輯:關於C語言

前言

本文整理 C 語言核心基礎知識點:有符號整數編碼、編譯鏈接流程、數據類型模型(ILP32/LP64)、常數後綴、常量存儲、scanf 掃描集與返回值、指針與下標效率差異、浮點格式 %f/%lf 差異,附 GDB 調試實證。

一、有符號整數編碼:原碼、反碼、補碼

1. 定義與示例(8 位示意)

值原碼反碼補碼
+60000 01100000 01100000 0110
-61000 01101111 10011111 1010
  • 正數:三碼相同
  • 負數:原碼符號位 1,數值位絕對值;反碼符號位不變,數值位按位取反;補碼 = 反碼 + 1
  • 計算機**統一用補碼**存儲、運算,因加減法統一、零唯一

2. 補碼特性

  • 對補碼再取補,得原碼(數值位)
  • 範圍:-[2^(n-1), 2^(n-1)-1],如 int8: -128~127
  • -x = ~x + 1(按位取反加一)

二、編譯流程四階段

源碼 (.c)
   ↓ 預處理 (cpp)  - 展開宏、頭文件、條件編譯、去除註釋
預處理輸出 (.i)
   ↓ 編譯 (cc1)    - 詞法/語法分析、優化、生成汇編
汇編碼 (.s)
   ↓ 汇編 (as)     - 汇編指令 → 機器碼目標文件
目標文件 (.o)
   ↓ 鏈接 (ld)     - 符號解析、地址重定位、合併段、生成可執行文件
可執行文件

三、數據類型模型:ILP32 vs LP64

關鍵差異:LP64 下 long 與指針 64 位,LLP64 下 long 仍 32 位,指針 64 位。跨平台代碼用 int32_t/int64_t/intptr_t(stdint.h)。

四、整數常數後綴與類型推導

類型ILP32 (32位 Unix)LP64 (64位 Unix/Linux)LLP64 (Windows 64位)
char888
short161616
int323232
long326432
long long646464
pointer326464
size_t326464
後綴類型(按優先級)示例
無int → long → long long100, 4000000000
u/Uunsigned int → unsigned long → unsigned long long100u, 4000000000U
l/Llong → long long100L
ul/UL/lu/LU 等unsigned long → unsigned long long100UL

無後綴十進制常數**首個能容納的有符號類型**;十六/八進制允許無符號類型。

五、常量在內存中的存儲

常量示例值存儲大小說明
整數字面量12 字節 (unsigned short)編譯器根據值大小選類型
字符字面量'1'1 字節 (char)ASCII 碼 0x31
字符串字面量"1"2 字節含結束符 \0,類型 const char[2]

六、scanf 掃描集、返回值與結束條件

1. 掃描集 %[...]

char buf[100];
scanf("%[^\n]", buf);  // 讀取整行(不含 \n)
scanf("%[a-z]", buf);  // 僅讀小寫字母

2. 返回值

  • 成功匹配並賦值的項數
  • 輸入失敗(匹配失敗)返回 0
  • 讀取到 EOF 且無數據匹配返回 EOF

3. 掃描結束條件

  1. 遇空白字符(空格、Tab、換行)
  2. 寬度滿
  3. 遇非法字符(不匹配格式)

七、指針 vs 下標:效率本質

// 方式 A:下標
for (i = 0; i < n; i++) a[i] = 4;
// 方式 B:指針
for (p = a; p < a + n; p++) *p = 4;

本質:a[i] 等價 *(a + i),每次計算地址需加法;指針版僅需遞增。現代編譯器(-O2)會**自動將下標循環優化為指針形式**(強度削減),手寫優化多為冗餘。可讀性優先。

八、%f vs %lf:浮點格式陷阱

1. printf:無差異

  • %f、%lf、%Lf 統一處理 double(float 會默認提升為 double)

2. scanf:關鍵差異

  • %f → float *(4 字節)
  • %lf → double *(8 字節)
  • %Lf → long double *

3. 實證:錯誤匹配後果

double y;
scanf("%f", &y);  // 錯誤:寫入 4 字節,高 4 字節殘留垃圾
// GDB 觀察:y = 4.85e-270(垃圾位模式被解釋為 double)

結論:scanf 讀 double **必須用 %lf**,讀 float 用 %f。printf 兩者通用。

九、總結

C 語言基礎看似枯燥,實則是**理解計算機系統運行機制的鑰匙**。補碼統一加減法、編譯鏈接揭示符號解析、數據模型決定跨平台移植性、scanf 格式匹配關乎內存安全、浮點格式區別反映類型系統嚴謹性。建議:配合 GDB 觀察內存佈局、彙編輸出、棧幀變化,將抽象概念落地為可見現象。

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