暑期自學嵌入式——Day02(C語言階段)

點關注不迷路喲。你的點贊、收藏,一鍵三連,是我持續更新的動力喲!!!

主頁:

一位搞嵌入式的 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~214748364732/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.143e53×10?)。

  • 科學計數法:應寫作 1.23e41.23×10?)。

  • 默認類型:未加后綴默認為 double 類型(加 f 后綴為 float,如 3.14f)。

標識常量(宏定義)

  • 別稱:也稱為宏定義(#define)。

  • 作用:用標識符代表常量值,提高代碼可讀性。

  • 語法格式#define 標識符 常量值(如 #define PI 3.14159)。

  • 預處理特性:在編譯前進行文本替換,不占用內存。

1)使用規范

  • 命名約定:通常使用全大寫字母,如 #define MAX 100

  • 作用范圍:從定義處開始到文件結束。

  • 類型安全:宏定義不進行類型檢查,僅做純文本替換。

2)優勢與局限

  • 優勢:

    • 便于集中修改常量值(如修改 PI 精度只需改定義處)。

    • 避免 “魔法數字”(直接寫 3.14 等無意義數值),提高代碼可維護性。

  • 局限:

    • 不占用內存空間(無存儲地址,調試時無法查看值)。

    • 替換可能引發邏輯錯誤(如 #define TWO 1+1TWO*2 會被替換為 1+1*2=3,需加括號 #define TWO (1+1))。

基本數據類型的常量(補充細節)

1)整型常量

  • 進制表示細節:

    • 八進制前綴 0 和十六進制前綴 0x 不可省略(如 077 是八進制 630x77 是十六進制 119)。

    • 二進制轉換關系:1 個八進制數對應 3 位二進制,1 個十六進制數對應 4 位二進制(如 0xF 對應 1111)。

    • 注意:C 語言不支持直接寫二進制常量(需用 0b 前綴的編譯器擴展,非標準)。

2)浮點常量

  • 精度分類:

    • 單精度(float):占 4 字節,精度約 6-7 位小數。

    • 雙精度(double):占 8 字節,精度約 15-17 位小數(默認類型)。

  • 指數形式規則:尾數可省略整數 / 小數部分(如 .5e3 等價 0.5×1035.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 = 553 - 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)變量的概念

  • 命名規則:

    • 組成:字母、數字、下劃線。

    • 限制:不能以數字開頭,不能與關鍵字重名(如 intif 等)。

  • 本質:程序中的存儲空間抽象,用于存放可變化的數據。

  • 地址特性:變量首地址可通過 & 運算符獲取(如 &num 表示變量 num 的地址)。

2)變量的存儲空間

  • 空間分配:

    • 大小由數據類型決定(如 int 占 4 字節,char 占 1 字節),與變量值無關。

    • 運行時實際占用內存空間,空間大小可通過 sizeof(變量名) 查看。

  • 地址特性:變量首地址可通過 & 運算符獲取,用于指針操作等場景。

變量的說明

  • 標準形式<存儲類型> <數據類型> <變量名> 示例:auto int age;static float score;

  • 存儲類型autoregisterstaticextern(決定變量的存儲方式和生命周期)。

  • 數據類型:基本類型(如 intfloat)或自定義類型(如結構體、數組)。

  • 默認情況:存儲類型 auto 可省略(如 int a; 等價于 auto int a;)。

變量的存儲類型

1)auto

  • 屬性:局部變量,默認存儲類型。

  • 作用范圍:限定在函數體或復合語句塊(如 iffor 塊)內。

  • 生命周期:進入作用域時創建,離開作用域時自動銷毀。

  • 默認值:未初始化時為隨機值(需手動初始化后使用)。

  • 應用案例: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 可直接處理的類型(如 intchar),長度不超過整型(通常 4 字節)。

    • 操作限制:不能使用 & 取地址(寄存器無內存地址),無法通過指針訪問。

    • 性能考量:過度使用可能導致寄存器資源緊張,反而降低性能,僅適用于高頻訪問的小型變量(如循環計數器)。

    • 示例

      #include <stdio.h>
      int main() {register int i; ?// 建議將i存入寄存器(適合循環計數)for (i = 0; i < 1000000; i++) {// 頻繁使用i,寄存器存儲可加速循環}// &i;  // 錯誤:不能對register變量取地址return 0;
      }

總結與思考

1)內容總結

  • 核心知識點:

    • 變量命名規范與存儲原理(大小由類型決定,占據實際內存)。

    • autoregister 存儲類型的特性(作用域、生命周期、使用場景)。

  • 關鍵區別:

    • 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. 文件 1(定義全局變量)file1.c

    int global_a = 100; ?// 全局變量定義(僅一次)
  2. 文件 2(引用全局變量)file2.c

    #include <stdio.h>
    extern int global_a; ?// 聲明外部變量(非定義)
    int main() {printf("global_a = %d\n", global_a); ?// 使用外部變量return 0;
    }
  3. 聯合編譯

    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 = 10b = 3

  • 運算結果:

    • 加法:a + b = 13

    • 減法:a - b = 7

    • 乘法:a * b = 30

    • 除法:a / b = 3(整數除法取商,舍棄小數)

    • 取余:a % b = 1(取余數)

  • 輸出格式:使用 %d 格式化輸出整型結果(如 printf("%d", a + b))。

例題:double 類型運算

  • 示例變量:設 x = 10.0y = 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 = 5b = 10

  • 運算分析:

    • a > b5 > 100(假)

    • a >= b5 >= 100(假)

    • a < b5 < 101(真)

    • a <= b5 <= 101(真)

    • a == b5 == 100(假)

    • a != b5 != 101(真)

  • 應用場景:主要用于條件判斷語句(如 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:判斷 ab 小于 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 拆分為 00010111,取反后為 11101000,組合為 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(無符號數)。

  • 注意事項:運算量和表達式都必須是整型數據類型(charintlong 等)。

位運算與移位操作

1. 十六進制與二進制轉換

  • 轉換方法:十六進制的每一位對應 4 位二進制(如 0x4 對應 01000xE 對應 11100xF 對應 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. 先計算表達式 1;

    2. 若為真(非 0),整個表達式取表達式 2 的值;

    3. 若為假(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 = 82score >= 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 為最低)。

  • 常見運算符優先級(從高到低)

    1. 括號(())、方括號([]);

    2. 單目運算符(!~++--sizeof);

    3. 算術運算符(*/% 高于 +-);

    4. 位運算符(<<>> 高于 &^|);

    5. 關系運算符(><>=<= 高于 ==!=);

    6. 邏輯運算符(&& 高于 ||);

    7. 三目運算符(?:);

    8. 賦值運算符(=+=-= 等);

    9. 逗號運算符(,)。

  • 易混淆點

    • 賦值運算符(=)優先級低于邏輯判斷運算符(==);

    • 邏輯與(&&)優先級高于邏輯或(||)。

  • 記憶技巧

    • 括號優先級最高,可強制改變運算順序;

    • 復雜表達式建議用括號明確順序(如 (a + b) * ca + 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(先自增后取值)的區別復合表達式中影響結果(如三目運算符、邏輯判斷中的自增時機)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914457.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914457.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914457.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何單獨安裝設置包域名

前言 在 npm 中&#xff0c;直接通過 package-lock.json 無法單獨設置包的安裝地址&#xff0c;因為該文件是自動生成的依賴關系鎖定文件。但你可以通過以下方法間接實現&#xff1a; 一、在 package.json 中指定包來源&#xff08;推薦&#xff09; 在 package.json 的 depend…

存儲過程探秘:數據庫編程的藝術

文章目錄存儲過程語法格式BEGIN...END語句塊DECLARE&#xff08;聲明局部變量&#xff09;流控制語句if函數批處理操作測試2測試3存儲過程與函數的關系存儲過程 MYSQL的存儲過程是一組預處理的SQL語句&#xff0c;可以像函數一樣在數據庫中進行存儲和調用。 它們允許在數據庫…

非阻塞寫入核心:asyncio.StreamWriter 的流量控制與數據推送之道

在 asyncio 的異步編程框架中&#xff0c;如果說 asyncio.StreamReader 是你異步應用的數據輸入管道&#xff0c;那么 asyncio.StreamWriter 就是你異步應用的數據輸出管道。它是一個至關重要的組件&#xff0c;讓你能夠方便、高效且非阻塞地向連接的另一端&#xff08;如 TCP …

控制臺打開mysql服務報錯解決辦法

控制臺打開mysql服務報錯解決辦法這個MySQL錯誤表示訪問被拒絕&#xff0c;通常是因為沒有提供正確的用戶名和密碼。以下是幾種解決方法&#xff1a; 方法1&#xff1a;指定用戶名和密碼連接 mysql -u root -p然后輸入root用戶的密碼。 方法2&#xff1a;如果忘記了root密碼&am…

Unsloth 實戰:DeepSeek-R1 模型高效微調指南(下篇)

食用指南 本系列因篇幅原因拆分為上下兩篇&#xff1a; 上篇以基礎環境搭建為主&#xff0c;介紹了 Unsloth 框架、基座模型下載、導入基座模型、數據集下載/加載/清洗、SwanLab 平臺賬號注冊。 下篇&#xff08;本文&#xff09;以實戰微調為主&#xff0c;介紹預訓練、全量…

Ubuntu安裝Jenkins

Ubuntu安裝Jenkins方法1&#xff1a;使用官方的Jenkins倉庫1. 添加Jenkins倉庫2. 更新軟件包列表3. 安裝Jenkins4. 啟動Jenkins服務5. 設置Jenkins開機啟動6. 查找初始管理員密碼7. 訪問Jenkins方法2&#xff1a;使用Snap包&#xff08;適用于較新的Ubuntu版本&#xff09;1. 安…

ubuntu22.04下配置qt5.15.17開發環境

自從qt5.15版本開始&#xff0c;不再提供免費的離線安裝包&#xff0c;只能通過源碼自行編譯。剛好最近需要在ubuntu22.04下配置qt開發環境&#xff0c;于是寫篇文章記錄配置的過程。 其實一開始是想配置qt5.15.2的&#xff0c;但是在編譯配置參數這一步驟中出現如下報錯 em…

S7-1200 與 S7-300 CPS7-400 CP UDP 通信 Step7 項目編程

S7-1200 CPU 與S7-300 CP STEP7 UDP通信S7-1200 與 S7-300 CP 之間的以太網通信可以通過 UDP 協議來實現&#xff0c;使用的通信指令是在S7-1200 CPU 側調用通信-開放式用戶通信TSEND_C&#xff0c;TRCV_C指令或TCON&#xff0c;TDISCON&#xff0c;TUSEND&#xff0c;TURCV 指…

基于YOLOv11的無人機目標檢測實戰(Windows環境)

1. 環境搭建 1.1 硬件與操作系統 操作系統&#xff1a;Windows 11 CPU&#xff1a;Intel i7-9700 GPU&#xff1a;NVIDIA RTX 2080&#xff08;8GB顯存&#xff09; 1.2 安裝CUDA和cuDNN 由于YOLOv11依賴PyTorch的GPU加速&#xff0c;需要安裝CUDA和cuDNN&#xff1a; 安…

Spring Cloud分布式配置中心:架構設計與技術實踐

從單體到微服務&#xff1a;Spring Cloud 開篇與微服務設計 Spring Cloud服務注冊與發現&#xff1a;架構設計與技術實踐深度分析 在以往分享中&#xff0c;碼友們已經掌握了微服務的設計和注冊中心的設計&#xff0c;部分聰明的碼友已經察覺了&#xff0c;已經到了需要設計一個…

15.2 Common Criteria合規

目錄1. Common Criteria簡介1.1 CC評估要素1.2 CC與TF-A的關系2. TF-A的CC合規要求2.1 安全功能需求2.2 開發過程要求3. TF-A的CC合規實現3.1 關鍵安全機制3.2 開發流程控制4. CC認證實踐指南4.1 認證準備步驟4.2 典型挑戰與解決方案4.3 已認證案例參考5. 持續合規建議1. Commo…

【前端:Typst】--let關鍵字的用法

在 Typst 中&#xff0c;#let 命令是用于定義變量和函數的核心指令&#xff0c;其用法非常靈活。以下是詳細的用法說明和示例。 目錄 1.基礎變量定義 2.函數定義 3.默認參數 4.內容塊參數&#xff08;Content Blocks&#xff09; 5.遞歸函數 1.基礎變量定義 // 定義簡單…

Qt輪廓分析設計+算法+避坑

輪廓分析擬合方面我現在只考慮矩形擬合和圓形擬合細分的話&#xff0c;橢圓擬合&#xff0c;矩形擬合&#xff0c;最小外接矩形&#xff0c;最小外接圓。對于一張圖像可能有不同的圖形&#xff0c;不同的圓&#xff0c;不同的矩形&#xff0c;我需要對其進行篩選&#xff0c;也…

C++中STL六大組件List的簡單介紹

一、前言C非常重視效率&#xff0c;對效率有損失的代碼常常是能省則省。使用list要包含的頭文件是<list>&#xff0c;要包含頭文件就是#iinclude <list>&#xff0c;List肯定是一種鏈表&#xff0c;我們不妨回憶一下那種鏈表插入刪除效率最快也就是最簡單&#xff…

第十五節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 - vue前端 生產部署

Vben Admin vben5 系列文章目錄 ?? 基礎篇 ? 第一節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 ? 第二節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 - Python Flask 后端開發詳解(附源碼) ? 第三節:Vben Admin 最新 v5.0 (vben5) + Python …

背包初步(0-1背包、完全背包)

當月光灑在我的臉上 我想我就快變了模樣 有一種叫做撕心裂肺的湯 喝了它有神奇的力量 動態規劃初步&#xff08;完全背包&#xff09; 目錄動態規劃初步&#xff08;完全背包&#xff09;0-1背包簡介完全背包檢查數組是否存在有效劃分&#xff08;前綴劃分DP&#xff09;單詞拆…

Linux驅動06 --- UDP

目錄 一、UDP 1.1 介紹 1.2 UDP 的通信方式 1.3 單播 發送函數 接收函數 1.4 廣播 1.5 組播/多播 一、UDP 1.1 介紹 傳輸層的另外一個協議 面向無連接&#xff0c;不穩定&#xff0c;速度快&#xff0c;可以一對多 UDP&#xff08;User Datagram Protocol&…

AJAX 投票:技術解析與應用場景

AJAX 投票:技術解析與應用場景 引言 隨著互聯網技術的不斷發展,Web應用的用戶體驗越來越受到重視。AJAX(Asynchronous JavaScript and XML)作為一種重要的技術,在實現異步數據交互方面發揮著關鍵作用。本文將深入探討AJAX投票系統的技術原理、應用場景以及優化策略。 A…

【字節跳動】數據挖掘面試題0017:推薦算法:雙塔模型,怎么把內容精準地推送給用戶

文章大綱 雙塔模型:推薦算法中的“高效匹配引擎一、雙塔模型的核心思想:“分而治之” 的匹配邏輯二、雙塔模型的結構:從特征輸入到相似度輸出1. 輸入層:特征的 “原材料處理”2. 塔網絡層:用戶與物品的“個性化編碼”3. 交互層:向量相似度的“偏好打分”三、雙塔模型的優…

7月14日日記

數學類今天考完最后一科英語放假回家了。有點羨慕他們。今天英語成績出來了&#xff0c;我是89分&#xff0c;一開始有點失望&#xff0c;感覺沒有上90&#xff0c;這是一個很好的沖擊4.0 的機會。但是后來一想好像也沒什么可惜的&#xff0c;這個分數還是很高的。舍友小林是90…