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

《C和指針》核心筆記(一):快速上手、數據模型與運算符深度解析

     編輯:關於C語言

第一章:快速上手要訣

  • 代碼邏輯刪除:用 #if 0 ... #endif 替代 /* */,避免嵌套註釋問題。
  • 預處理:#include 文本替換,#define 定義常量/宏(類似 Java final static)。
  • 頭文件複用:共享聲明放入 .h,#include 引入,單一拷貝易維護。
  • 函數原型:便於編譯器檢查調用準確性,跨文件調用必備。
  • 數組名 即首元素地址,&arr 雖合法但多餘。
  • scanf 以空白分隔(%c 除外),字符串不可含空白。
  • 數組越界:標準不要求檢查,需自查,否則破壞相鄰內存。
  • scanf 返回值:成功轉換數,失敗返回 0,EOF 返回 EOF。
  • gets/puts:gets 讀行丟棄 \n 加 \0;puts 輸出加 \n。
  • getchar/putchar:單字符 I/O,getchar 返回 int(含 EOF),putchar 輸出字符碼。

編譯鏈接流程

編輯 → 預處理 → 編譯(.o) → 鏈接(a.out) → 加載 → 運行
UNIX: cc welcome.c → a.out

第二章:數據模型詳解

整型位寬與範圍

類型最小範圍備註
char0~127有符號性由實現定義
signed char-127~127
unsigned char0~255
short-32767~32767≥16位
unsigned short0~65535
int-32767~32767≥16位,通常=機器字長
unsigned int0~65535
long-2147483647~2147483647≥32位
unsigned long0~4294967295

limits.h 定義 CHAR_BIT, SCHAR_MIN/MAX, UCHAR_MAX, SHRT_MIN/MAX, USHRT_MAX, INT_MIN/MAX, UINT_MAX, LONG_MIN/MAX, ULONG_MAX。

字符有符號性判斷

#if ('\x80' < 0)
#define CHAR_MIN SCHAR_MIN
#define CHAR_MAX SCHAR_MAX
#else
#define CHAR_MIN 0
#define CHAR_MAX UCHAR_MAX
#endif

整型常量類型推導

  • 十進制:int → long → unsigned long(取最小容納者)。
  • 八/十六進制:int → unsigned int → long → unsigned long。
  • 負號為一元運算符,非常量一部分。
  • 字符常量類型為 int;L'x' 為寬字符。

浮點類型

long double ≥ double ≥ float,最小範圍 10±37。常量默認 double,F/f→float,L/l→long double。

字符串常量

  • 以 \0 結尾,內部不可含 \0。
  • "" 為空串(含 1 字節 \0)。
  • ANSI C:修改字符串常量屬 UB,編譯器可合併相同常量。

指針聲明陷阱

int *a, b, c;  // 僅 a 是指針,b/c 是 int
char *msg = "Hello";  // 初始化 msg 本身,非 *msg

作用域與鏈接

  • 四種作用域:文件、函數、塊、原型。
  • 塊內同名遮蔽外層;函數參數屬同一塊,不可重複定義(ANSI)。
  • 鏈接:external(跨文件可見)、internal(文件內可見)、none(唯一實體)。
  • static 將 external 改為 internal;extern 聲明 external。
  • 塊外變量默認靜態存儲;塊內默認自動存儲(棧)。

第三章:運算符深度解析

移位運算符可移植性陷阱

  • 無符號右移:邏輯右移(高位補 0)。
  • 有符號右移:算術/邏輯由實現定義 → 不可移植。
  • 示例:char ch; while((ch=getchar())!=EOF) 錯誤!EOF 需更多位,getchar 返回 int。

賦值運算符優化

a[2*(y-6*f(x))] = a[2*(y-6*f(x))] + 1;  // 下標計算兩次
a[2*(y-6*f(x))] += 1;                     // 僅計算一次,效率更高

sizeof 運算符

  • 操作數可為表達式(不求值)或類型名(需括號)。
  • sizeof 1 → 4(int),sizeof (char) → 1。
  • 數組名作操作數返回整個數組字節數。

自增自減副作用陷阱

  • Java: a = a++ → 1;b = ++b → 2。
  • C: a = a++ / b = ++b 均為未定義行為(UB),編譯器結果不一致。
  • c + --c:求值順序未規定,結果不可移植。

逗號運算符

expr1, expr2, expr3 左→右求值,整體值為最後表達式值。

下標與指針等價

arr[i] ≡ *(arr + i),編譯器統一轉換為指針形式。

結構訪問

  • . 用於變量,-> 用於指針。
  • ++p->len ≡ ++(p->len);*p->str++ 先取值後 str++;*p++->str 先取值後 p++。

邏輯真假

0 為假,非 0 為真。flag 只能為 0/1 時 if(flag) 等價 if(flag==TRUE);任意整數時需顯式 if(flag != 0)。

指針作為左值/右值

*p = 20;  // 左值:指定修改位置
a = *p;   // 右值:提取位置值

整數溢出防範

long c = a * (long)b;  // 強轉一操作數避免 16位機溢出

求值順序規則

  • 相鄰運算符:優先級高者先算;同優先級按結合性。
  • 非相鄰/無副作用:編譯器可自由重排(如 a*b + c*d 三乘法順序不定)。
  • 函數調用參數求值順序未規定:f()+g()+h() 中 f,g,h 調用順序不定。
  • 受限運算符:&& || ? : , 強制左→右求值。

經典優先級/結合性案例

  1. a = b = c → 右結合 → a = (b = c)。
  2. *p++ → *(p++)(後綴 ++ 優先級高於 *)。
  3. x > y ? 100 : ++y > 2 ? 20 : 30 → 右結合 → x > y ? 100 : (++y > 2 ? 20 : 30)。條件運算符強制先算條件,x>y 為真則整體為 100,內層不求值(無副作用)。

位翻轉算法(可移植寫法)

unsigned int reverse_bits(unsigned int value) {
    unsigned int ans = 0;
    for (unsigned int i = 1; i != 0; i <<= 1) {
        ans <<= 1;
        if (value & 1) ans |= 1;
        value >>= 1;
    }
    return ans;
}
// 25 (0x00000019) → 2550136832 (0x98000000)

用 i != 0 控制循環次數,自適應機器字長,避免硬編碼 32/64。

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