點關注不迷路喲。你的點贊、收藏,一鍵三連,是我持續更新的動力喲!!!
主頁:
一位搞嵌入式的 genius-CSDN博客https://blog.csdn.net/m0_73589512?spm=1000.2115.3001.5343
目錄
Day02→數據類型(上)
數據類型分類
基本數據類型
整形數據類型
字符型數據類型
實型數據類型
構造數據類型
特殊數據類型
布爾類型詳解
基本概念
使用注意事項
預處理分析
知識小結
Day02→數據類型(下)
char類型
short 類型
short 類型與 unsigned short 類型的定義
short 類型與 int 類型的長度區別
示例:打印類型長度
short 類型值域的分析
int 類型
limits.h 頭文件
頭文件作用
文件位置與包含方式
主要宏定義內容
實際應用示例
使用建議
知識小結
Day02→常量
常量定義
基本數據類型常量
1)整型常量
2)浮點型常量
標識常量(宏定義)
1)使用規范
2)優勢與局限
基本數據類型的常量(補充細節)
1)整型常量
2)浮點常量
3)指數常量
4)字符常量
5)字符串常量
應用案例(精選)
例題:字符常量運算
例題:宏定義的文本替換
知識小結
Day02→嵌入式開發變量(一)
作業講解
變量的基礎
1)變量的概念
2)變量的存儲空間
變量的說明
變量的存儲類型
1)auto
2)register
總結與思考
1)內容總結
知識小結
Day02→嵌入式開發變量(二)
static 存儲類型
定義與特性
1)static 局部變量示例
代碼對比
關鍵現象
2)static 局部變量的特點
extern 存儲類型
定義與使用條件
1)extern 全局變量示例
典型錯誤
正確用法
2)總結與思考
知識小結
Day02→運算符(1)
算術運算符
1)C 語言提供的算術運算符
例題:整數加減乘除運算
例題:double 類型運算
關系運算符
1)C 語言的關系運算符
例題:關系運算符運算
邏輯運算符
1)邏輯非 ! 運算符的運算律
例題:邏輯非運算符使用
2)邏輯與 && 運算符的運算規律
例題:if 條件語句邏輯與運算
3)邏輯或 || 運算符的運算規律
例題:邏輯或運算符使用
運算符總結
1. 算術運算符
2. 關系運算符
3. 邏輯運算符
4. 例題:邏輯運算求值
知識小結
Day02→運算符(2)
位運算符基礎
1)C 語言的位運算符
位邏輯反運算符(~)
位邏輯與運算符(&)
位邏輯或運算符(|)
位邏輯異或運算符(^)
2)位移位運算
移位運算的一般形式
位運算與移位操作
1. 十六進制與二進制轉換
2. 左移運算原理
3. 例題:驗證左移運算
4. 移位運算的數學本質
知識小結
Day02→運算符(3)
位運算的核心應用與例題解析
1. 思考
2. 例題:無符號數置 1
3. 例題:無符號數清 0
4. 例題:十進制轉十六進制(位運算優化)
位運算的應用價值與學習建議
應用價值
學習建議
知識小結
Day02→運算符(4)
賦值運算符
1)基本賦值運算符
2)賦值復合運算符
例題:賦值復合運算符應用
特殊運算符
1)條件運算符(三目運算符)
例題:三目運算符應用
例題:三目運算符與自增結合
2)逗號運算符
例題:逗號運算符應用
3)sizeof 運算符
運算符的優先級
1)優先級表(核心規則)
例題:運算符優先級應用
知識小結
Day02→數據類型(上)
數據類型分類
基本數據類型
-
分類依據:根據存儲范圍和正負特性選擇數據類型,主要考慮數據大小范圍和是否需要存儲負數。
-
主要類型:
-
整形:包括有符號(signed)和無符號(unsigned)兩種形式。
-
字符型:char 類型,實際也分有符號和無符號兩種。
-
實型:float 和 double 用于存儲小數。
-
枚舉型:enum 類型。
-
-
存儲特性:
-
有符號數可存儲正負數,無符號數只能存儲≥0 的數。
-
范圍從小到大:short < int < long < long long。
-
整形數據類型
-
符號區分:
-
有符號數:用 signed 表示,可存儲正負數。
-
無符號數:用 unsigned 表示,只能存儲≥0 的數。
-
-
范圍區分:
-
short:短整型。
-
int:基本整型。
-
long:長整型。
-
long long:超長整型。
-
-
選擇原則:
-
根據數據是否可能為負數選擇有 / 無符號。
-
根據數據大小范圍選擇合適的數據類型。
-
字符型數據類型
-
基本形式:char 類型。
-
特殊性質:
-
實際上也分為有符號和無符號兩種形式。
-
字符的 ASCII 碼值可以視為某種形式的整型。
-
-
存儲特性:
-
可存儲單個字符。
-
底層存儲的是字符對應的 ASCII 碼值。
-
實型數據類型
-
主要類型:
-
float:單精度浮點型。
-
double:雙精度浮點型。
-
-
應用場景:
-
用于存儲小數數據。
-
需要更高精度時使用 double 類型。
-
構造數據類型
-
定義:用戶自定義的數據類型,非基礎類型。
-
主要類型:
-
數組。
-
結構體(struct)。
-
共用體(union)。
-
-
特點:
-
需要用戶自行定義。
-
可以組合基本類型構建更復雜的數據結構。
-
特殊數據類型
-
指針類型:
-
用于存儲內存地址。
-
是 C 語言的重要特性。
-
-
空類型(void):
-
用于說明不返回值的函數。
-
也可用于指向類型的指針。
-
布爾類型詳解
基本概念
-
類型名稱:bool。
-
值域:
-
true(非零值,通常為 1)。
-
false(零值)。
-
-
賦值方式:
-
直接賦值為 true/false。
-
賦值為非零 / 零值。
-
-
判斷規則:非零值為真,零值為假。
使用注意事項
-
頭文件要求:
-
需要包含
<stdbool.h>
頭文件。 -
否則會報 “unknown type name” 錯誤。
-
-
底層實現:
-
實際是 C99 標準引入的
_Bool
類型。 -
true 和 false 是宏定義,分別為 1 和 0。
-
-
賦值特性:
-
賦值為負數(-1)時,仍視為真值(非零)。
-
但實際存儲時會轉換為 1。
-
預處理分析
-
預處理命令:
gcc -E bool.c -o bool.i
。 -
頭文件位置:
/usr/lib/gcc/x86_64-linux-gnu/11/include/stdbool.h
。 -
宏定義內容:
#define bool _Bool #define true 1 #define false 0
-
替代方案:
-
可直接使用
_Bool
類型。 -
但仍需頭文件來使用 true/false。
-
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 |
---|---|---|---|
數據類型概述 | C 語言學習路徑:數據類型→常量 / 變量→運算符→控制語句→輸入輸出→數組 / 字符串→指針 / 函數 | 數據類型分類邏輯(基本類型 / 構造類型 / 指針類型 / 空類型) | ?? |
布爾類型 | - 需引入 stdbool.h 頭文件;- 本質為_Bool 基本類型(C99 新增);- 真值規則:非零為真(true=1),零為假(false=0) | - 未引入頭文件時直接使用 bool 會報錯;- 宏定義陷阱:true/false 實際為頭文件定義的宏(值固定為 1/0) | ??? |
整型分類邏輯 | 根據范圍(short/int/long/long long)和符號性(signed/unsigned)劃分 | - long long 與 long 范圍差異;- 字符型本質屬于特殊整型(可參與數值運算) | ???? |
浮點型 | float(單精度)與 double(雙精度)的存儲精度差異 | 默認小數常量類型為 double(需加 f 后綴顯式聲明為 float) | ?? |
類型轉換 | - 隱式轉換規則(小類型→大類型);- 強制轉換語法:(目標類型) 變量 | 符號擴展問題(如 char 轉 int 時符號位填充) | ??? |
編程實踐要點 | - 強調同步編碼驗證(如布爾值打印測試);- 預處理命令 gcc -E 分析頭文件展開 | 易錯點:布爾變量賦值為 - 1 時實際存儲值為 1(因宏替換) |
Day02→數據類型(下)
char類型
1 #include <stdio.h>2 #include <stdbool.h>3 4 // argc:命令行參數的個數(包含程序名本身)5 6 int main(int argc, char *argv[]) {7 ? ? ? ? unsigned char ch;8 ? ? ? ? ch = -1;9 ? ? ? ? printf("ch = %d %c\n",ch,ch);10 11 ? ? ? ? return 0;12 13 } ? 那這份代碼為什么最后打印出來的是255???
解答:
在這段代碼中,打印出 255 主要和 unsigned char 類型以及數據的存儲、類型轉換規則有關,以下是詳細解釋: 1. 數據存儲 char 類型如果是有符號的,其取值范圍是 -128 到 127,如果是 unsigned char,取值范圍是 0 到 255 。在代碼中,變量 ch 被聲明為 unsigned char 類型。 當執行 ch = -1; 時,-1 是一個有符號整數,在計算機中,有符號整數以補碼形式存儲,-1 的 8 位補碼是 1111 1111 。將 -1 賦值給 unsigned char 類型的變量 ch 時,編譯器會直接把 -1 的補碼值 1111 1111 存儲到 ch 對應的內存空間中 。因為 unsigned char 類型不區分符號位,所以這個 1111 1111 就被解釋為無符號數 。 2. 類型轉換與打印 printf 函數中,%d 格式說明符用于打印整數。當使用 %d 打印 unsigned char 類型的變量 ch 時,會發生類型提升。由于 unsigned char 是小于 int 類型的整型,在表達式求值時,會將 unsigned char 類型的值提升為 int 類型 。 對于 unsigned char 類型,在提升過程中,會在高位補 0 ,1111 1111 提升為 int 類型后就是 0000 0000 0000 0000 0000 0000 1111 1111 ,對應的無符號十進制值就是 255 ,所以打印出 255 。 而對于 %c 格式說明符,它會將 ch 的值作為 ASCII 碼值來解析對應的字符。ASCII 碼中,碼值 255 對應的字符是不可打印的控制字符,所以通常會看到一個亂碼或者不顯示字符 。 總結來說,是 unsigned char 類型對數據的解釋方式,以及 printf 函數在打印時的類型提升規則,導致了打印出 255 這個結果。
short 類型
short 類型與 unsigned short 類型的定義
-
存儲長度:short 類型占用 2 個字節存儲空間。
-
有符號范圍:signed short 值域為 - 32768~32767。
-
無符號范圍:unsigned short 值域為 0~65535。
short 類型與 int 類型的長度區別
-
操作系統影響:在 32 位系統中,short 長度為 2 字節,int 長度為 4 字節。
-
符號處理:兩者都可以存儲負數,使用 signed 修飾符表示有符號類型。
示例:打印類型長度
-
測量方法:使用 sizeof 運算符獲取類型長度。
-
典型結果:
-
bool 類型:1 字節
-
char 類型:1 字節
-
short 類型:2 字節
-
int 類型:4 字節
-
-
實現限制:sizeof 最小單位為字節,不能測量更小的位數。
short 類型值域的分析
-
位數計算:2 字節 = 16 位,無符號最大值為(2^{16}-1=65535)。
-
有符號范圍:-32768 到 32767,最高位為符號位。
-
應用場景:適合存儲 6 萬以下的數值,如工資等中等規模數據。
int 類型
-
存儲長度:固定占用 4 字節存儲空間。
-
無符號范圍:0~4294967295((2^{32}-1))。
-
有符號范圍:-2147483648~2147483647。
-
空間規模:相當于 4GB 的尋址空間。
-
計算技巧:可通過(2^{n}-1)(n 為總位數)快速估算最大取值范圍。
limits.h 頭文件
頭文件作用
-
數據類型范圍查詢:當數據類型長度較長時(如 int、long 等),直接記憶其值域范圍較為困難,limits.h 頭文件提供了各數據類型的范圍宏定義。
-
避免手動計算:通過包含該頭文件可直接使用預定義的常量值,無需手動計算數據類型的邊界值。
文件位置與包含方式
-
標準位置:位于 /usr/include/ 目錄下。
-
包含語法:
#include <limits.h>
。
主要宏定義內容
-
字符型范圍:
-
有符號 char: -128~127(SCHAR_MIN~SCHAR_MAX)
-
無符號 char: 0~255(UCHAR_MAX)
-
字節定義: CHAR_BIT 宏定義為 8,表示 1 字節 = 8 位
-
-
short 類型范圍:
-
有符號 short: -32768~32767(SHRT_MIN~SHRT_MAX)
-
無符號 short: 0~65535(USHRT_MAX)
-
-
整型范圍:
-
有符號 int: -2147483648~2147483647(INT_MIN~INT_MAX)
-
無符號 int: 0~4294967295(UINT_MAX)
-
-
long 類型范圍:
-
有符號 long: -9223372036854775808~9223372036854775807(LONG_MIN~LONG_MAX)
-
無符號 long: 0~18446744073709551615(ULONG_MAX)
-
實際應用示例
-
程序演示:
#include <stdio.h> #include <limits.h> ? int main() {printf("有符號int最小值:%d\n", INT_MIN);printf("有符號int最大值:%d\n", INT_MAX);printf("無符號int最大值:%u\n", UINT_MAX);return 0; }
-
輸出結果:
有符號int最小值:-2147483648 有符號int最大值:2147483647 無符號int最大值:4294967295
使用建議
-
編程實踐:在需要獲取數據類型邊界值時直接使用 limits.h 中的宏定義。
-
記憶技巧:只需記住各類型字節長度,具體范圍可通過頭文件查詢。
-
驗證方法:編寫簡單測試程序打印各宏定義值,與理論值進行比對。
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 |
---|---|---|---|
布爾類型 | 基本數據類型介紹,可賦值的范圍及長度 | 布爾類型的實際存儲方式(通過整型實現) | ?? |
字符型 (char) | 1 字節長度,有符號 (-128~127) 和無符號 (0~255) 范圍 | 負 128 的特殊補碼表示 (10000000),ASCII 碼轉換規則 | ???? |
整型 (short/int) | short (2 字節) 范圍:-32768~32767,int (4 字節) 范圍:-2147483648~2147483647 | 32/64 位系統下 long 類型長度差異,使用 sizeof 測試環境 | ??? |
數據范圍計算 | 二進制補碼原理,原碼 / 反碼 / 補碼轉換 | 負數的補碼計算規則,邊界值溢出問題(如 128 變成 - 128) | ???? |
limits.h 頭文件 | 預定義各類型極值常量(CHAR_MIN/CHAR_MAX 等) | 實際開發中替代手動計算范圍的方法 | ?? |
類型安全賦值 | 越界的隱式轉換風險(如 char 賦 128 轉為 - 128) | 編譯器不報錯但運行異常的情況處理 | ???? |
ASCII 編碼 | 字符與整數的映射關系(如 65 對應 'A') | 非打印字符的顯示問題(如 12 |
Day02→常量
常量定義
-
概念:常量是在整個程序運行期間值不會發生變化的數據。
-
特點:與變量相對,常量值在定義后不可修改。
-
分類依據:基于基本數據類型進行分類。
基本數據類型常量
-
基礎:依托于基本數據類型(整型、浮點型等)的常量表示。
-
賦值規范:不同數據類型對應的常量值有特定書寫格式要求。
-
重要性:是編程基礎且使用頻率極高的知識點。
1)整型常量
-
表示方法+:
-
十進制:直接書寫數字,如
123
。 -
八進制:以
0
開頭,如0123
(表示十進制83
)。 -
十六進制:以
0x
開頭,如0x1A
(表示十進制26
)。
-
2)浮點型常量
-
標準形式:必須包含小數點或指數,如
3.14
或3e5
(3×10?
)。 -
科學計數法:應寫作
1.23e4
(1.23×10?
)。 -
默認類型:未加后綴默認為
double
類型(加f
后綴為float
,如3.14f
)。
標識常量(宏定義)
-
別稱:也稱為宏定義(
#define
)。 -
作用:用標識符代表常量值,提高代碼可讀性。
-
語法格式:
#define 標識符 常量值
(如#define PI 3.14159
)。 -
預處理特性:在編譯前進行文本替換,不占用內存。
1)使用規范
-
命名約定:通常使用全大寫字母,如
#define MAX 100
。 -
作用范圍:從定義處開始到文件結束。
-
類型安全:宏定義不進行類型檢查,僅做純文本替換。
2)優勢與局限
-
優勢:
-
便于集中修改常量值(如修改
PI
精度只需改定義處)。 -
避免 “魔法數字”(直接寫
3.14
等無意義數值),提高代碼可維護性。
-
-
局限:
-
不占用內存空間(無存儲地址,調試時無法查看值)。
-
替換可能引發邏輯錯誤(如
#define TWO 1+1
,TWO*2
會被替換為1+1*2=3
,需加括號#define TWO (1+1)
)。
-
基本數據類型的常量(補充細節)
1)整型常量
-
進制表示細節:
-
八進制前綴
0
和十六進制前綴0x
不可省略(如077
是八進制63
,0x77
是十六進制119
)。 -
二進制轉換關系:1 個八進制數對應 3 位二進制,1 個十六進制數對應 4 位二進制(如
0xF
對應1111
)。 -
注意:C 語言不支持直接寫二進制常量(需用
0b
前綴的編譯器擴展,非標準)。
-
2)浮點常量
-
精度分類:
-
單精度(
float
):占 4 字節,精度約 6-7 位小數。 -
雙精度(
double
):占 8 字節,精度約 15-17 位小數(默認類型)。
-
-
指數形式規則:尾數可省略整數 / 小數部分(如
.5e3
等價0.5×103
,5.e-2
等價5.0×10?2
)。
3)指數常量
-
結構組成:尾數 +
e/E
+ 指數(如1.23e-4
表示1.23×10??
)。 -
應用場景:
-
特別大的數(如地球質量
5.97e24
千克)。 -
特別小的數(如電子電荷量
1.602e-19
庫侖)。
-
-
優勢:避免書寫大量零,表達更簡潔(
0.0000000035
可寫為3.5e-9
)。
4)字符常量
-
定義:由單引號括起的單個字符,如
'A'
、'0'
、'+'
。 -
本質:存儲的是對應 ASCII 碼值(如
'A'
實際存儲65
,'0'
存儲48
)。 -
表示方式:
-
直接寫字符:
'a'
(ASCII 碼97
)。 -
用 ASCII 碼值:
97
(等價于'a'
)。
-
-
運算特性:
可參與整數運算(實際是對 ASCII 碼值運算),例如:
-
大寫轉小寫:
'A' + 32 = 'a'
(65 + 32 = 97
)。 -
字符數字轉數值:
'5' - 48 = 5
(53 - 48 = 5
)。
-
5)字符串常量
-
定義:用雙引號括起的字符序列,如
"Hello"
、"123"
。 -
存儲特點:自動以
'\0'
(空字符,ASCII 碼0
)結尾,例如"a"
實際存儲'a'
和'\0'
,共 2 字節。 -
與字符常量的區別:
類型 表示符號 存儲內容 示例對比 字符常量 單引號 單個字符(1 字節) 'a'
占 1 字節字符串常量 雙引號 字符序列 + '\0'
"a"
占 2 字節('a'+'\0'
)
應用案例(精選)
例題:字符常量運算
#include <stdio.h> int main() {char c1 = 'B' + 3; ? ? ? // 'B'(66) + 3 = 69 → 'E'char c2 = 'b' - 32; ? ? ?// 'b'(98) - 32 = 66 → 'B'int num = '9' - '0'; ? ? // '9'(57) - '0'(48) = 9printf("%c %c %d\n", c1, c2, num); ?// 輸出:E B 9return 0; }
例題:宏定義的文本替換
#include <stdio.h> #define ONE 1 #define TWO ONE + ONE ?// 注意:未加括號 int main() {int a = 2;int res = TWO * a; ?// 替換為 1 + 1 * 2 → 3(非預期的 4)printf("%d\n", res);return 0; } // 修正:#define TWO (ONE + ONE),則 res = (1+1)*2 = 4
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 |
---|---|---|---|
基本數據類型常量 | 整型(十進制 / 八進制 / 十六進制)、浮點型(常規 / 科學計數法) | 八進制以 0 開頭、十六進制以 0x 開頭;科學計數法中 e 代表 10 的冪 | ★★☆☆☆ |
字符常量 | 單引號表示,ASCII 碼轉換(大小寫差 32,數字字符轉數值差 48) | '0' (ASCII 48)≠ 0(數值);大寫轉小寫需加 32,而非直接改字母 | ★★★☆☆ |
字符串常量 | 雙引號表示,隱含 '\0' 結尾 | "a" 占 2 字節(含 '\0' ),與 'a' (1 字節)的區別 | ★★★☆☆ |
標識常量(宏) | #define 定義,預處理文本替換 | 宏展開不做運算(需加括號避免歧義);無類型檢查,可能引發隱蔽錯誤 | ★★★★☆ |
常量綜合應用 | 科學計數法表示極值、宏定義提高可維護性(如水分子數量計算) | 浮點數精度問題;宏替換后的運算符 |
Day02→嵌入式開發變量(一)
作業講解
-
作業要求:編寫程序計算指定夸脫水中的水分子數量。
-
解題思路:
-
使用宏定義常量:水分子質量(如
3.0e-23g
)和 1 夸脫質量(950g
)。 -
計算公式:總水分子數 = (夸脫數
n
× 950) / 水分子質量。 -
使用浮點數類型(
float
)存儲變量。 -
輸出采用科學計數法格式(
%e
)。
-
-
實現要點:
-
需處理極小值(水分子質量)和極大值(計算結果)的數值范圍。
-
注意
scanf
讀取浮點數時應使用%f
格式而非%d
。
-
變量的基礎
1)變量的概念
-
命名規則:
-
組成:字母、數字、下劃線。
-
限制:不能以數字開頭,不能與關鍵字重名(如
int
、if
等)。
-
-
本質:程序中的存儲空間抽象,用于存放可變化的數據。
-
地址特性:變量首地址可通過
&
運算符獲取(如&num
表示變量num
的地址)。
2)變量的存儲空間
-
空間分配:
-
大小由數據類型決定(如
int
占 4 字節,char
占 1 字節),與變量值無關。 -
運行時實際占用內存空間,空間大小可通過
sizeof(變量名)
查看。
-
-
地址特性:變量首地址可通過
&
運算符獲取,用于指針操作等場景。
變量的說明
-
標準形式:
<存儲類型> <數據類型> <變量名>
示例:auto int age;
、static float score;
-
存儲類型:
auto
、register
、static
、extern
(決定變量的存儲方式和生命周期)。 -
數據類型:基本類型(如
int
、float
)或自定義類型(如結構體、數組)。 -
默認情況:存儲類型
auto
可省略(如int a;
等價于auto int a;
)。
變量的存儲類型
1)auto
-
屬性:局部變量,默認存儲類型。
-
作用范圍:限定在函數體或復合語句塊(如
if
、for
塊)內。 -
生命周期:進入作用域時創建,離開作用域時自動銷毀。
-
默認值:未初始化時為隨機值(需手動初始化后使用)。
-
應用案例:auto 變量使用示例
#include <stdio.h> int main() {int a = 10; ?// 省略auto,默認是auto變量if (a > 5) {auto int b = 20; ?// 塊內auto變量printf("b = %d\n", b); ?// 輸出:20}// printf("b = %d\n", b); // 錯誤:b在if塊外不可訪問return 0; }
-
注意事項:
-
局部變量作用域嚴格受限,跨作用域訪問會報錯。
-
使用前必須初始化,否則可能讀取到隨機垃圾值。
-
2)register
-
設計目的:建議編譯器將頻繁訪問的變量存儲在 CPU 寄存器中,以加速訪問(寄存器訪問速度遠快于內存)。
-
硬件限制:
-
寄存器數量有限(32 位 CPU 通常僅幾十個)。
-
數據長度限制(32 位 CPU 最大支持 4 字節,64 位 CPU 最大支持 8 字節)。
-
-
實現機制:
-
編譯器可忽略該建議(若寄存器不足或變量不適合存寄存器),自動轉為
auto
類型。
-
-
使用注意事項:
-
類型限制:必須是 CPU 可直接處理的類型(如
int
、char
),長度不超過整型(通常 4 字節)。 -
操作限制:不能使用
&
取地址(寄存器無內存地址),無法通過指針訪問。 -
性能考量:過度使用可能導致寄存器資源緊張,反而降低性能,僅適用于高頻訪問的小型變量(如循環計數器)。
-
示例:
#include <stdio.h> int main() {register int i; ?// 建議將i存入寄存器(適合循環計數)for (i = 0; i < 1000000; i++) {// 頻繁使用i,寄存器存儲可加速循環}// &i; // 錯誤:不能對register變量取地址return 0; }
-
總結與思考
1)內容總結
-
核心知識點:
-
變量命名規范與存儲原理(大小由類型決定,占據實際內存)。
-
auto
和register
存儲類型的特性(作用域、生命周期、使用場景)。
-
-
關鍵區別:
-
auto
:常規局部變量,自動內存管理,作用域限于代碼塊。 -
register
:建議放入寄存器的優化變量,適用于高頻訪問的小型數據,不可取地址。
-
-
實踐要點:
-
注意變量作用域和生命周期,避免跨作用域訪問錯誤。
-
合理使用
register
優化關鍵變量(如循環計數器),但避免過度使用。
-
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 |
---|---|---|---|
變量基礎概念 | 變量是程序中的存儲空間抽象,占據內存空間,大小由數據類型決定 | 變量名規則:字母 / 數字 / 下劃線組成,不能以數字開頭;與關鍵字重名錯誤 | ?? |
auto 存儲類型 | 默認存儲類型,局部變量,作用域限定在代碼塊內 | 未初始化時值為隨機數;作用域外無法訪問(編譯報錯) | ??? |
register 存儲類型 | 建議編譯器將變量存儲在 CPU 寄存器中,無法取地址 | 僅適用于頻繁訪問的小型數據(≤4 字節);實際可能仍存內存(編譯器可忽略建議) | ???? |
宏定義應用 | 通過 #define 定義常量(如水分子質量 3.0e-23 ),提高代碼可讀性 | 宏替換是預處理階段完成,無類型檢查(可能引發類型不匹配問題) | ?? |
科學計數法表示 | 使用浮點數指數形式(如 3.0e-23 )處理極小 / 極大值 | 輸出時用 %e 或 %g 格式;注意浮點數精度損失問題 | ?? |
變量作用域 | 演示 if 代碼塊內變量在外部不可訪問 | 塊作用域({} 內)與函數作用域的區別;局部變量與全局變量的作用域差異 | ??? |
數據類型選擇 | 示例中使用 float 處理可能的大數值結果 | 浮點型(精度有限)與整型(無小數)的精度取舍;根據數值范圍選擇合適類型 |
Day02→嵌入式開發變量(二)
static 存儲類型
定義與特性
-
定義:
static
變量稱為靜態存儲類型變量,可在函數體內(局部)或函數體外(全局)聲明。 -
默認值:未初始化時默認值為
0
(與全局變量一致,區別于auto
變量的隨機值)。 -
作用范圍:
-
修飾局部變量:延長生命周期至程序結束,但作用域仍限于原代碼塊。
-
修飾全局變量:限制作用域為當前文件(其他文件無法訪問)。
-
1)static 局部變量示例
代碼對比
// 普通局部變量(auto) #include <stdio.h> void func() {int a = 0; ?// 每次調用重新初始化a++;printf("%d ", a); } int main() {for (int i = 0; i < 4; i++) {func(); ?// 輸出:1 1 1 1}return 0; }
// static局部變量 #include <stdio.h> void func() {static int a = 0; ?// 僅初始化一次,保留上次值a++;printf("%d ", a); } int main() {for (int i = 0; i < 4; i++) {func(); ?// 輸出:1 2 3 4}return 0; }
關鍵現象
-
未顯式初始化時,
static
變量默認從0
開始(如上述示例輸出1 2 3 4
)。 -
顯式初始化后,從初始值累加(如
static int a = 5
,則輸出6 7 8 9
)。
2)static 局部變量的特點
-
存儲方式:存于全局數據區(固定地址),而非棧內存(區別于
auto
變量)。 -
生命周期:從程序啟動到結束(持續存在,不隨代碼塊銷毀)。
-
調用特性:
-
僅在第一次進入作用域時初始化,后續調用不再重新聲明。
-
保留上次調用的結果(如累加器、計數器場景)。
-
-
與 auto 的區別:
特性 auto 局部變量 static 局部變量 默認值 隨機值 0 存儲位置 棧內存 全局數據區 生命周期 隨代碼塊銷毀 程序全程存在 初始化時機 每次進入作用域 僅第一次進入作用域
extern 存儲類型
定義與使用條件
-
定義:
extern
稱為外部引用類型,用于引用其他文件中定義的全局變量(聲明而非定義)。 -
使用條件:
-
被引用變量必須是全局變量(在函數體外定義)。
-
編譯時需將多個文件聯合編譯(否則無法找到變量定義)。
-
-
語法格式:
extern 數據類型 變量名;
(如extern int global_num;
)。
1)extern 全局變量示例
典型錯誤
-
未聲明
extern
直接使用:編譯報錯undeclared identifier
。 -
未聯合編譯:即使聲明
extern
,鏈接時仍報錯undefined reference
。
正確用法
-
文件 1(定義全局變量):
file1.c
int global_a = 100; ?// 全局變量定義(僅一次)
-
文件 2(引用全局變量):
file2.c
#include <stdio.h> extern int global_a; ?// 聲明外部變量(非定義) int main() {printf("global_a = %d\n", global_a); ?// 使用外部變量return 0; }
-
聯合編譯:
gcc file1.c file2.c -o main ?# 鏈接兩個文件 ./main ?# 輸出:global_a = 100
2)總結與思考
-
static 修飾全局變量的效果:將全局變量的作用域限制為當前文件(其他文件即使使用
extern
也無法訪問),實現 “文件級封裝”。 -
extern 與 static 的關系:
-
extern
可引用普通全局變量(未被static
修飾)。 -
extern
無法引用static 全局變量(受限于作用域)。
-
-
四種存儲類型對比:
存儲類型 核心特性 典型應用場景 auto 局部變量,棧內存,自動銷毀 函數內臨時變量 register 建議存寄存器,無地址,加速訪問 循環計數器、高頻訪問變量 static 局部:延長生命周期;全局:限制作用域 累加器、文件內部全局變量 extern 跨文件引用全局變量,聲明而非定義 多文件共享全局數據
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 |
---|---|---|---|
static 修飾局部變量 | 1. 默認初始化為 0;2. 生命周期延長至程序結束;3. 作用域不變 | 與 auto 的區別:默認值(0 vs 隨機)、生命周期(程序全程 vs 代碼塊內) | ??? |
static 修飾全局變量 | 限制全局變量僅在當前文件可見,禁止跨文件訪問 | 與普通全局變量的對比:普通可跨文件訪問,static 僅當前文件可見 | ?? |
extern 關鍵字 | 聲明外部全局變量,需聯合編譯多個文件 | 常見錯誤:未聲明 extern、未聯合編譯;與 static 全局變量的沖突 | ???? |
存儲類型對比 | auto(棧)、static(全局區)、extern(跨文件)、register(寄存器) | 生命周期維度:auto < static = extern;作用域維度:static 全局 < 普通全局 | ???? |
實驗驗證案例 | static 局部變量累加、多文件 extern 引用、static 全局變量限制訪問 | static 局部變量的 “初始化僅一次” 特性;extern 的 “聲明而非定義” 本質 |
Day02→運算符(1)
算術運算符
1)C 語言提供的算術運算符
-
運算符類型:包括
+
(加)、-
(減)、*
(乘)、/
(除)、%
(取余)、++
(自增)、--
(自減)。 -
書寫規范:
-
乘法符號:編程中使用
*
代替數學中的×
。 -
除法符號:使用左斜杠
/
代替數學中的÷
。 -
運算符間距:建議運算符兩邊加空格(如
a + b
),提高代碼可讀性。
-
-
特殊限制:
-
取余運算:僅適用于整型數據,
float
/double
等浮點類型不能進行取余運算。 -
雙目運算符:加減乘除取余都需要兩個運算量(如
a + b
)。 -
單目運算符:自增自減為單目運算符(如
i++
、--j
)。
-
例題:整數加減乘除運算
-
示例變量:設
a = 10
,b = 3
。 -
運算結果:
-
加法:
a + b = 13
-
減法:
a - b = 7
-
乘法:
a * b = 30
-
除法:
a / b = 3
(整數除法取商,舍棄小數) -
取余:
a % b = 1
(取余數)
-
-
輸出格式:使用
%d
格式化輸出整型結果(如printf("%d", a + b)
)。
例題:double 類型運算
-
示例變量:設
x = 10.0
,y = 3.0
。 -
運算特點:
-
浮點除法:
x / y = 3.333333
(保留小數部分)。 -
取余限制:浮點數不能使用
%
運算符,會導致編譯錯誤(如x % y
報錯)。
-
-
輸出格式:使用
%f
或%lf
格式化輸出浮點結果(如printf("%.2f", x / y)
)。 -
錯誤處理:需要注釋掉浮點取余的代碼才能通過編譯。
關系運算符
1)C 語言的關系運算符
-
運算符類型:包括
>
(大于)、>=
(大于等于)、<
(小于)、<=
(小于等于)、==
(等于)、!=
(不等于)。 -
書寫規范:
-
等于判斷:必須使用雙等號
==
,與賦值運算符=
嚴格區分(如a == 5
是判斷,a = 5
是賦值)。 -
不等判斷:使用
!=
組合表示(如a != 0
表示 “a 不等于 0”)。
-
-
運算結果:返回邏輯值(
1
表示真,0
表示假)。
例題:關系運算符運算
-
示例變量:設
a = 5
,b = 10
。 -
運算分析:
-
a > b
→5 > 10
→0
(假) -
a >= b
→5 >= 10
→0
(假) -
a < b
→5 < 10
→1
(真) -
a <= b
→5 <= 10
→1
(真) -
a == b
→5 == 10
→0
(假) -
a != b
→5 != 10
→1
(真)
-
-
應用場景:主要用于條件判斷語句(如
if
)和循環條件(如while
)。
邏輯運算符
1)邏輯非 !
運算符的運算律
-
基本運算:包含邏輯反(非
!
)、邏輯與(&&
)、邏輯或(||
)三種運算符。 -
運算規律:
-
邏輯非:對運算量取反,
真
變假
,假
變真
。
-
-
運算示例:
-
!a
:判斷a
不等于0
(若a
非 0,則!a
為 0;若a
為 0,則!a
為 1)。 -
a > 0 && a < 100
:判斷a
在 0 到 100 之間。 -
a < 10 || b < 10
:判斷a
或b
小于 10。
-
例題:邏輯非運算符使用
-
運算規則:
-
當運算量為
真
(非 0)時,結果為0
(假)。 -
當運算量為
假
(0)時,結果為1
(真)。
-
-
代碼示例
int a = 5; printf("%d\n", !a); ?// 輸出0(a非0,!a為假) int b = 0; printf("%d\n", !b); ?// 輸出1(b為0,!b為真)
-
注意事項:
-
通常會對整個表達式加括號來明確優先級,例如:
!(a > b)
是對a > b
整體取反。
-
2)邏輯與 &&
運算符的運算規律
-
運算規則:
-
只有左右運算量都為
真
(非 0)時,結果才為1
(真)。 -
其他情況結果均為
0
(假)。
-
-
短路特性:
-
從左到右依次處理,當左運算量為
假
(0)時,右運算量不執行(逢 0 截止)。
-
-
示例分析:
int a = 0, b = 5; int res = (a != 0) && (b++); ?// 左為假,右不執行,b仍為5 printf("%d %d\n", res, b); ? ?// 輸出0 5
例題:if 條件語句邏輯與運算
-
題目解析:
-
當
(a > 0) && (b > 0)
成立時,才會執行printf
。 -
若
a = -1
,則整個表達式為假,printf
不會執行。
-
-
易錯點:
-
注意短路特性可能導致某些表達式不被執行(如上述示例中
b++
未執行)。 -
變量初始化和使用順序要明確。
-
3)邏輯或 ||
運算符的運算規律
-
運算規則:
-
只要有一個運算量為
真
(非 0),結果就為1
(真)。 -
只有兩個都為
假
(0)時,結果才為0
(假)。
-
-
短路特性:
-
從左到右依次處理,當左運算量為
真
(非 0)時,右運算量不執行(逢 1 截止)。
-
例題:邏輯或運算符使用
-
題目解析:
int a = 5, b = 10; int res = (a > 0) || (b++); ?// 左為真,右不執行,b仍為10 printf("%d %d\n", res, b); ? // 輸出1 10
-
注意事項:
-
與邏輯與相反,邏輯或是 “見 1 就停”。
-
注意區分
||
(邏輯或)和|
(位或)運算符的區別。
-
運算符總結
1. 算術運算符
-
基本運算:包含加減乘除(
+
、-
、*
、/
)和取模運算(%
)。 -
浮點型注意:對
float
/double
類型無需特殊處理,直接使用基本運算符即可,但不支持%
。
2. 關系運算符
-
比較運算:包含小于(
<
)、小于等于(<=
)、大于(>
)、大于等于(>=
)、相等(==
)、不等(!=
)等。 -
結果特性:返回布爾值(0 或 1),用于條件判斷。
3. 邏輯運算符
-
短路特性:邏輯與(
&&
)是 “逢零截止”,邏輯或(||
)是 “逢一截止”。 -
執行特點:部分表達式可能因短路特性而不會被執行。
-
使用注意:
-
邏輯與:當第一個操作數為假時,第二個操作數不會執行。
-
邏輯或:當第一個操作數為真時,第二個操作數不會執行。
-
4. 例題:邏輯運算求值
-
題目解析
(設
x = 5
,
y = 18
):
-
示例 1:
x > 0 && y < 20
→ 結果為 1(x=5
滿足,y=18
滿足)。 -
示例 2:
x > 0 && y < 10
→ 結果為 0(y=18
不滿足)。 -
示例 3:
x < 0 && y < 20
→ 結果為 0(x=5
不滿足)。 -
示例 4:
x > 0 || y < 10
→ 結果為 1(x=5
滿足第一個條件)。 -
示例 5:
x < 0 || y < 20
→ 結果為 1(y=18
滿足第二個條件)。
-
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 | ||
---|---|---|---|---|---|
算術運算符 | 加減乘除、取余(% )操作;float /double 不支持取余運算 | 取余運算僅限整數;乘法用 * 代替 × ,除法用 / 代替 ÷ | ?? | ||
關系運算符 | 大小比較(> , >= , < , <= )、相等(== )與不等(!= ) | 雙等號 == 與賦值 = 的區別;表達式結果為 0(假)或 1(真) | ?? | ||
邏輯運算符 | 邏輯與(&& )、邏輯或(` | )、邏輯非( !`) | 短路特性:邏輯與:逢 0 截止,邏輯或:逢 1 截止;未執行的表達式可能影響變量值 | ??? | |
運算符優先級與規范 | 空格規范(如 a + b )、括號明確優先級 | ++ /-- 的前后置差異;復雜表達式建議用括號分組 | ?? | ||
數據類型與運算限制 | int 支持完整算術運算;float /double 禁用取余 | float 除法精度問題;混合類型運算的隱式轉換 | ??? | ||
代碼實踐示例 | 演示整形 / 浮點運算差異;邏輯運算短路驗證(如 b++ 未執行案例) | if 條件中的副作用(如 |
Day02→運算符(2)
位運算符基礎
1)C 語言的位運算符
-
運算基礎:位運算以二進制為基礎,需熟練掌握進制轉換和原碼 / 反碼 / 補碼知識。
-
效率優勢:比算術運算符效率更高,在嵌入式開發中常用于精準控制硬件寄存器(如設置特定引腳電平)。
位邏輯反運算符(~)
-
符號表示:
~
(單目運算符)。 -
運算規則:按位取反,0 變 1,1 變 0。
-
無符號數處理:直接對全部位取反,不考慮符號位(因無符號數無符號位)。
-
例題:字符取反計算
-
示例分析: 定義
unsigned char x = 0x17
(二進制00010111
),取反后~x
得到11101000
(十六進制0xE8
)。 -
驗證方法:將十六進制每位轉 4 位二進制后整體取反(如
0x17
拆分為0001
和0111
,取反后為1110
和1000
,組合為0xE8
)。 -
打印技巧:使用
printf("%#x", y)
可自動添加0x
前綴(如輸出0xe8
)。
-
位邏輯與運算符(&)
-
符號表示:
&
(雙目運算符)。 -
運算規則:兩位都為 1 時結果為 1,否則為 0(即 “全 1 則 1,有 0 則 0”)。
-
清零技巧:用 0 與任何位相與可實現該位清零(如
a & 0xFE
可清零最低位)。 -
應用場景:嵌入式開發中精準控制寄存器特定位(如讀取某引腳狀態時屏蔽其他位)。
-
例題:字符與運算
-
示例分析: 設
a = 056
(八進制,二進制01010110
),b = 0xac
(十六進制,二進制10101100
),則a & b
結果為00000100
(十六進制0x04
)。 -
驗證要點:按位比對,只有第 3 位(從 0 開始計數)同時為 1,故結果對應位為 1。
-
位邏輯或運算符(|)
-
符號表示:
|
(雙目運算符)。 -
運算規則:兩位有 1 時結果為 1,全 0 時才為 0(即 “有 1 則 1,全 0 則 0”)。
-
置位技巧:用 1 或任何位可實現該位置 1(如
a | 0x01
可將最低位置 1)。 -
例題:字符或運算
-
示例分析: 設
a = 036
(八進制,二進制00111110
),b = 0x89
(十六進制,二進制10001001
),則a | b
結果為10111111
(十六進制0xBF
)。 -
計算技巧:逐位觀察,只要兩位中至少有 1,則結果位為 1。
-
位邏輯異或運算符(^)
-
符號表示:
^
(雙目運算符)。 -
運算規則:兩位相異為 1,相同為 0(即 “同 0 異 1”)。
-
特殊性質:
-
一個數異或自己結果為 0(
a ^ a = 0
)。 -
一個數異或 0 保持原值(
a ^ 0 = a
)。
-
-
例題:字符異或運算
-
示例分析: 設
a = 75
(十進制,二進制01001011
),b = 0173
(八進制,二進制01111011
),則a ^ b
結果為00110000
(十六進制0x30
或八進制060
)。 -
記憶口訣:“同 0 異 1” 可快速判斷異或結果。
-
2)位移位運算
移位運算的一般形式
-
基本語法:
<運算量> <運算符> <整型表達式>
(如a << 3
,表示a
左移 3 位)。 -
運算符類型:
-
左移
<<
:高位丟棄,低位補 0。 -
右移
>>
:低位丟棄,高位補符號位(有符號數)或 0(無符號數)。
-
-
注意事項:運算量和表達式都必須是整型數據類型(
char
、int
、long
等)。
位運算與移位操作
1. 十六進制與二進制轉換
-
轉換方法:十六進制的每一位對應 4 位二進制(如
0x4
對應0100
,0xE
對應1110
,0xF
對應1111
)。 -
補位規則:當二進制位數不足時,在前面補零使其達到數據類型要求的位數(如
unsigned char
為 8 位,0x4
補位后為00000100
)。
2. 左移運算原理
-
操作定義:
a << 3
表示將變量a
的二進制位左移 3 位,右邊空出的位補 0。 -
位移特性:
-
左移一位相當于乘以 2,左移 n 位相當于乘以
2?
(無溢出情況下)。 -
移出的高位直接丟棄,低位補零。
-
對于無符號數(如
unsigned char
),最高位移出不會產生符號問題(因無符號位)。
-
-
實例演示:
0xE4
(二進制11100100
)左移 3 位后,高位 3 位丟棄,低位補 3 個 0,得到00100000
(十六進制0x20
)。
3. 例題:驗證左移運算
-
題目解析:
代碼實現:
#include <stdio.h> int main() {unsigned char x = 0xe4; ?// 二進制 11100100unsigned char y = x << 3;printf("y = %#x\n", y); ?// 輸出 y = 0x20return 0; }
-
運行結果:驗證得到
y = 0x20
,與理論計算結果一致。 -
易錯點:需注意數據類型是否為無符號數,有符號數的左移可能因符號位變化導致結果異常(如溢出后變為負數)。
4. 移位運算的數學本質
-
數學規律:
-
左移 1 位相當于乘以 2(
a << 1 = a * 2
)。 -
左移 2 位相當于乘以 4(
a << 2 = a * 4
)。 -
左移 3 位相當于乘以 8(
a << 3 = a * 8
)。
-
-
二進制演示
(以
0x04
為例):
-
初始值:
00000100
(4)。 -
左移 1 位:
00001000
(8 = 4 * 2)。 -
左移 2 位:
00010000
(16 = 4 * 4)。 -
左移 3 位:
00100000
(32 = 4 * 8)。
-
-
記憶口訣:“左移乘二,右移除二”,可快速計算移位結果(無溢出時)。
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 | |||
---|---|---|---|---|---|---|
位運算符基礎 | 位運算以二進制為基礎,與邏輯運算的區別;無符號數處理規則 | 進制轉換(16 進制 / 8 進制 / 二進制);取反操作對無符號數的影響 | ?? | |||
位運算類型 | 邏輯與(& )、邏輯或(` | )、取反( ~)、異或( ^`)的運算規則及示例 | 異或運算 “同 0 異 1” 特性;與 / 或運算的清零 / 置位技巧 | ??? | ||
移位運算 | 左移(<< )與右移(>> )操作;左移等價于乘 2 的冪次方 | 移位后補位規則(左移補 0,右移區分有符號 / 無符號);無符號數移位與符號位問題 | ?? | |||
位運算應用場景 | 提高程序效率(優于加減乘除);嵌入式開發中寄存器精準控制 | 硬件寄存器操作中的位掩碼設計(如用 & 讀取特定位,用 ` | ` 設置特定位) | ???? | ||
實踐驗證方法 | 通過代碼示例驗證位運算結果,強調手動計算與程序輸出對比 | 16 進制 / 二進制轉換的準確性;移位運算中的溢出問題 | ?? | |||
易錯點總結 | 混淆邏輯運算符(&& /` |
Day02→運算符(3)
位運算的核心應用與例題解析
1. 思考
-
基本運算符:包括位邏輯反(
~
)、位邏輯與(&
)、位邏輯或(|
)、位邏輯異或(^
)、位邏輯移位(<<
和>>
)。 -
核心應用:通過位運算可以精準控制數據的特定位(如設置為 1、清零、翻轉等),在硬件寄存器操作中尤為重要(例如控制 GPIO 引腳電平、配置外設功能等)。
2. 例題:無符號數置 1
-
實現原理: 利用位邏輯或(
|
) 的特性:1 與任何位進行或運算結果必為 1,0 與任何位進行或運算保持原值。通過構造 “目標位為 1,其余位為 0” 的掩碼,與原數進行或運算,即可將目標位置 1。 -
掩碼構造: 將 1 左移
(y-1)
位生成僅目標位為 1 的掩碼(如y=2
時,1 << 1 = 00000010
,掩碼為0x02
)。 -
代碼實現:
#include <stdio.h> int main() {unsigned char x = 0x04; ?// 二進制 0100int y = 2; ? ? ? ? ? ? ? // 目標位(從1開始計數)x = x | (1 << (y - 1)); ?// 第2位置1,掩碼為 00000010printf("0x%x\n", x); ? ? // 輸出 0x6(二進制 0110)return 0; }
-
驗證過程:0x4(0100)的第 2 位置 1 后變為 0x6(0110),符合預期。
3. 例題:無符號數清 0
-
實現原理: 利用位邏輯與(
&
) 的特性:0 與任何位進行與運算結果必為 0,1 與任何位進行與運算保持原值。通過構造 “目標位為 0,其余位為 1” 的掩碼,與原數進行與運算,即可將目標位清零。 -
掩碼構造: 先構造目標位為 1 的掩碼(
1 << (y-1)
),再對其取反(~
),得到目標位為 0、其余位為 1 的掩碼(如y=3
時,~(1 << 2) = ~00000100 = 11111011
)。 -
代碼實現:
#include <stdio.h> int main() {unsigned char x = 0x14; ?// 二進制 00010100int y = 3; ? ? ? ? ? ? ? // 目標位(從1開始計數)x = x & ~(1 << (y - 1)); // 第3位清零,掩碼為 11111011printf("0x%x\n", x); ? ? // 輸出 0x10(二進制 00010000)return 0; }
-
驗證過程:0x14(00010100)的第 3 位(從右數)清零后變為 0x10(00010000),目標位成功清零。
4. 例題:十進制轉十六進制(位運算優化)
-
數學原理:
十六進制的每位對應 4 位二進制,因此可用位運算替代除法和取余:
-
取整替代:
a / 16
等價于a >> 4
(右移 4 位,丟棄低 4 位,相當于除以 16)。 -
取余替代:
a % 16
等價于a & 0xF
(與 0xF(二進制 1111)運算,保留低 4 位,即余數)。
-
-
代碼對比:
#include <stdio.h> int main() {int a = 65;// 常規方法int quotient1 = a / 16; ? // 商為4int remainder1 = a % 16; ?// 余為1// 位運算方法int quotient2 = a >> 4; ? // 右移4位,商為4int remainder2 = a & 0xF; // 與0xF,余為1printf("常規:商%d 余%d\n", quotient1, remainder1);printf("位運算:商%d 余%d\n", quotient2, remainder2);return 0; }
-
驗證過程:65(十六進制 0x41)轉換后商為 4、余為 1,兩種方法結果一致,位運算更高效。
位運算的應用價值與學習建議
應用價值
位運算在底層開發(如嵌入式、驅動開發)中具有高效(直接操作二進制,無需復雜運算)、精準(可單獨控制某一位)的優勢,特別適合硬件寄存器操作(如配置外設、讀寫狀態位等)。
學習建議
-
反復練習掩碼構造(如何生成目標位的掩碼)和位操作技巧(置 1、清零、翻轉、提取位等)。
-
掌握位運算與常規運算的等價轉換(如右移替代除法、與運算替代取余),理解其效率優勢。
-
結合硬件場景練習(如模擬寄存器配置),加深對 “位級控制” 的理解。
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 | |
---|---|---|---|---|
位運算基礎 | 邏輯與(& )、邏輯或(` | )、異或( ^)、位移( <</ >>`)的操作規則 | 位運算與邏輯運算的區別;移位方向與結果的關系 | ?? |
位操作應用 | 無符號數特定位操作(置 1 / 清零);利用掩碼實現精準控制 | 或運算(` | )置1與與運算( &`)清零的區別;掩碼構造的邏輯 | ??? |
置 1 操作實現 | `x = x | (1 << (y-1))`(如 0x4 第 2 位置 1→0x6) | 左移位數與目標位的對應關系(y-1 的計算邏輯) | ?? |
清零操作實現 | x = x & ~(1 << (y-1)) (如 0x14 第 3 位清零→0x10) | 取反操作(~ )的優先級;掩碼取反后的位分布 | ??? | |
進制轉換 | 十進制轉十六進制:右移 4 位替代 ÷16,與 0xF 替代 %16 | 位運算替代數學運算的原理;0xF 的作用(保留低 4 位) | ???? | |
硬件寄存器控制 | 位運算精準控制硬件寄存器特定位(如配置 GPIO、外設功能) | 實際應用中掩碼的設計(如何覆蓋目標位);多比特位同時操作的技巧 |
Day02→運算符(4)
賦值運算符
1)基本賦值運算符
-
基本形式:
=
,如int a = 5;
-
執行特點:將右值表達式的計算結果賦給左值變量(左值必須是可修改的變量,不能是常量或表達式)。
-
常見誤區:編程中的
=
表示賦值,而非數學中的 “相等” 關系(判斷相等用==
)。
2)賦值復合運算符
-
簡化原理:
a += b
等價于a = a + b
,其他運算符同理。 -
運算符類型:
-
算術類:
+=
、-=
、*=
、/=
、%=
-
位運算類:
&=
、|=
、^=
、<<=
、>>=
-
-
使用優勢:簡化代碼書寫,減少變量重復書寫,部分編譯器可優化執行效率。
例題:賦值復合運算符應用
#include <stdio.h> int main() {int sum = 0, count = 1;while (count++ < 20) { ?// 先判斷后自增,累加到20sum += count; ? ? ? // 等價于 sum = sum + count}printf("sum = %d\n", sum); ?// 輸出:210(1到20的累加和)return 0; }
-
代碼解析:
-
sum += count
簡化了累加操作,循環變量count
初始化為 1,通過自增控制循環次數。 -
計算結果為 1 到 20 的累加和(210),驗證了復合運算符的實用性。
-
特殊運算符
1)條件運算符(三目運算符)
-
語法結構:
表達式1 ? 表達式2 : 表達式3
-
執行邏輯:
-
先計算表達式 1;
-
若為真(非 0),整個表達式取表達式 2 的值;
-
若為假(0),取表達式 3 的值。
-
-
等價關系:相當于簡化的
if-else
結構(如a > b ? a : b
等價于if(a > b) return a; else return b;
)。
例題:三目運算符應用
#include <stdio.h> int main() {int score = 82;// 成績分級:≥101→100,90-100→90,<90→60int res = (score >= 101) ? 100 : (score < 90 ? 60 : 90);printf("res = %d\n", res); ?// 輸出:60(82<90,取60)return 0; }
-
變量分析:
-
score = 82
,score >= 101
不成立 → 進入第二個三目運算; -
score < 90
成立 → 取 60,最終結果為 60。
-
例題:三目運算符與自增結合
#include <stdio.h> int main() {int x = 70, y;// 版本1:先比較后自增(x++ > 80 中x先取值70,再自增為71)y = (x++ > 80) ? 100 : 0; ?printf("版本1:x=%d, y=%d\n", x, y); ?// 輸出:71, 0x = 70; ?// 重置x// 版本2:先自增后比較(++x > 80 中x先自增為71,再比較)y = (++x > 80) ? 100 : 81; ?printf("版本2:x=%d, y=%d\n", x, y); ?// 輸出:71, 81return 0; }
-
關鍵點:區分
x++
(先取值后自增)和++x
(先自增后取值)的執行時機,直接影響結果。
2)逗號運算符
-
語法特點:用括號包含多個表達式,以逗號分隔(如
(表達式1, 表達式2, ..., 表達式n)
)。 -
執行規則:
-
從左到右依次執行各個表達式;
-
整個表達式的值為最后一個表達式的值。
-
-
典型應用:
-
多變量初始化:
int a = 1, b = 2, c = 3;
-
復合運算:
for (i=0, j=10; i<j; i++, j--)
。
-
例題:逗號運算符應用
#include <stdio.h> int main() {float x = 5.5, y = 1.8;float res = (x *= 3, y += 1.0, x + y); ?// 逗號表達式// 執行步驟:// 1. x *= 3 → x = 16.5// 2. y += 1.0 → y = 2.8// 3. 取最后一個表達式 x + y → 19.3printf("res = %.1f\n", res); ?// 輸出:19.3(可能有浮點精度誤差)return 0; }
3)sizeof 運算符
-
功能作用:計算數據類型或變量所占內存的字節數。
-
使用形式:
-
類型:
sizeof(數據類型)
(如sizeof(int)
); -
變量:
sizeof(變量名)
或sizeof 變量名
(如sizeof(a)
或sizeof a
)。
-
-
32 位系統典型值:
-
int
:4 字節;long
:4 字節;long long
:8 字節;char
:1 字節。
-
-
注意事項:結果由數據類型決定,與變量的具體值無關(如
int a = 0; sizeof(a)
仍為 4 字節)。
運算符的優先級
1)優先級表(核心規則)
-
優先級規則:表中優先級從上到下依次降低(數值越小優先級越高,如 1 為最高,15 為最低)。
-
常見運算符優先級(從高到低):
-
括號(
()
)、方括號([]
); -
單目運算符(
!
、~
、++
、--
、sizeof
); -
算術運算符(
*
、/
、%
高于+
、-
); -
位運算符(
<<
、>>
高于&
、^
、|
); -
關系運算符(
>
、<
、>=
、<=
高于==
、!=
); -
邏輯運算符(
&&
高于||
); -
三目運算符(
?:
); -
賦值運算符(
=
、+=
、-=
等); -
逗號運算符(
,
)。
-
-
易混淆點:
-
賦值運算符(
=
)優先級低于邏輯判斷運算符(==
); -
邏輯與(
&&
)優先級高于邏輯或(||
)。
-
-
記憶技巧:
-
括號優先級最高,可強制改變運算順序;
-
復雜表達式建議用括號明確順序(如
(a + b) * c
比a + b * c
更清晰)。
-
例題:運算符優先級應用
#include <stdio.h> int main() {int x = 1, y = 0, z = 0;// 邏輯與(&&)優先級高于邏輯或(||)int result = x++ && y++ || ++z;// 執行順序:// 1. x++ && y++ → x先取值1(后自增為2),y先取值0(后自增為1),邏輯與結果為0// 2. 0 || ++z → 計算++z(z變為1),邏輯或結果為1printf("result = %d, x=%d, y=%d, z=%d\n", result, x, y, z);// 輸出:result=1, x=2, y=1, z=1return 0; }
知識小結
知識點 | 核心內容 | 考試重點 / 易混淆點 | 難度系數 | ||||
---|---|---|---|---|---|---|---|
復合賦值運算符 | += 、-= 、*= 等簡化寫法(如 a += b 等價于 a = a + b ) | 自增 / 自減與復合運算的結合(如 count++ < 20 先判斷后自增) | ?? | ||||
三目運算符 | 表達式1 ? 表達式2 : 表達式3 ,等價于簡化的 if-else | 執行順序:先判斷表達式 1,再選擇表達式 2/3;與自增結合時的執行時機 | ??? | ||||
逗號運算符 | 多個表達式從左到右執行,結果為最后一個表達式的值 | 優先級最低,與賦值或邏輯運算結合時需加括號(如 (a=1, b=2, a+b) ) | ???? | ||||
sizeof 運算符 | 計算變量或類型的內存字節數(如 sizeof(int) ) | 結果由類型決定,與變量值無關;區分 sizeof(a) 和 sizeof(a[0]) (數組場景) | ? | ||||
運算符優先級 | 括號 > 算術 > 關系 > 邏輯 > 賦值 > 逗號 | == 優先級高于 = (如 if(x = y == 1) 易出錯);邏輯與優先級高于邏輯或 | ???? | ||||
短路特性 | 邏輯與(&& )逢 0 截止,邏輯或(` | `)逢 1 截止 | 結合優先級分析短路條件(如 `x++ && y++ | z++` 中邏輯與優先執行) | ??? | ||
自增 / 自減陷阱 | x++ (先取值后自增)與 ++x (先自增后取值)的區別 | 復合表達式中影響結果(如三目運算符、邏輯判斷中的自增時機) |