/********************************************************************
* @brief @param @return @author @date @version是代碼書寫的一種規范
* @brief :簡介,簡單介紹函數作用
* @param :介紹函數參數
* @return:函數返回類型說明
* @exception NSException 可能拋出的異常.
* @author zhangsan: 作者
* @date 2011-07-27 22:30:00 :時間
* @version 1.0 :版本
* @property :屬性介紹
* *********************************************************************/
【變量的命名習慣】
變量名是自定義的,嚴格遵循 標識符 命名規則。
- 見名知意
- 大駝峰:即每個單詞首字母都大寫,例如:
MyName
- 小駝峰:即第二個(含)以后的單詞首字母大寫,例如:
myName
- 小寫+下劃線:例如:
my_name
個人風格分享
1.變量
-
全局變量:小駝峰(小駝峰+下劃線),例如
myName
或my_Name
-
局部變量: 全小寫(小寫+下劃線),例如
index
或my_name
2.常量: 全大寫字母、下劃線分隔單詞和描述性名稱
#define MAX_BUFFER_SIZE 1024
#define PI_VALUE 3.14159
#define DEFAULT_TIMEOUT 30
3.標志變量
- 全局:
g_
+ 小駝峰 + 下劃線,例如g_has_Err
- 局部:
g_
+ 全小寫 + 下劃線 , 例如g_has_err
4.函數名 大駝峰(大駝峰+下劃線), 例如 GetValue
, Get_Value()
動詞+名詞結構 ,例如
GetValue
,Get_Value()
5.結構體 大駝峰(大駝峰 + 下劃線),例如
// 定義結構體
typedef struct {int id; // 結構體成員局部的用小寫char name[50];int age;
} StudentInfo;
// Student_Info
6.枚舉 : 枚舉成員名使用全大寫字母, 前綴標識枚舉成員
typedef enum {STATUS_SUCCESS, // 前綴標識枚舉成員STATUS_ERROR, // 全大寫字母STATUS_PENDING
} StatusCode;
// Status_Code;
總結就是凡是有帶大寫的都跟全局有關,凡是標志位夠加g_
,常量用全大寫字母表示。
在C語言編程中,良好的命名規則有助于提高代碼的可讀性、可維護性和可擴展性。以下是一些值得學習和遵守的命名規則:
-
變量命名規則:
- 使用小寫字母,單詞之間用下劃線分隔,例如:
student_age
,total_sum
,index
。 - 變量名應具有描述性,反映其用途或含義。
- 使用小寫字母,單詞之間用下劃線分隔,例如:
-
常量命名規則:
- 使用全大寫字母,單詞之間用下劃線分隔,例如:
MAX_BUFFER_SIZE
,PI_VALUE
。 - 常量名通常使用
#define
或const
關鍵字定義。
- 使用全大寫字母,單詞之間用下劃線分隔,例如:
-
函數命名規則:
- 使用動詞或動詞短語開頭,后接名詞,單詞之間用下劃線分隔,例如:
calculate_sum
,print_student_info
。 - 函數名應清晰描述其功能或操作。
- 使用動詞或動詞短語開頭,后接名詞,單詞之間用下劃線分隔,例如:
-
結構體和聯合體命名規則:
- 結構體和聯合體類型名使用大寫字母開頭,每個單詞的首字母大寫,例如:
StudentInfo
,EmployeeRecord
。 - 結構體變量名使用小寫字母,單詞之間用下劃線分隔,例如:
student_info
,employee_record
。
- 結構體和聯合體類型名使用大寫字母開頭,每個單詞的首字母大寫,例如:
-
枚舉命名規則:
- 枚舉類型名使用大寫字母開頭,每個單詞的首字母大寫,例如:
Color
,Status
。 - 枚舉成員名使用全大寫字母,單詞之間用下劃線分隔,例如:
RED
,GREEN
,SUCCESS
,FAILURE
。
- 枚舉類型名使用大寫字母開頭,每個單詞的首字母大寫,例如:
-
文件名規則:
- 文件名應簡潔且具有描述性,通常使用小寫字母,單詞之間用下劃線分隔,例如:
main.c
,student_info.h
。
- 文件名應簡潔且具有描述性,通常使用小寫字母,單詞之間用下劃線分隔,例如:
-
縮寫和簡寫:
- 盡量避免使用不常見的縮寫和簡寫,如果使用縮寫,確保其含義清晰并在代碼中有解釋。
-
命名長度:
- 命名長度應適中,過長的名字會影響可讀性,過短的名字則可能不夠描述性。一般推薦變量名長度在3-20個字符之間。
-
前綴和后綴:
- 使用前綴或后綴區分不同作用域或用途的變量,例如:全局變量使用
g_
前綴,靜態變量使用s_
前綴,指針變量使用_ptr
后綴。
- 使用前綴或后綴區分不同作用域或用途的變量,例如:全局變量使用
通過遵守這些命名規則,可以使代碼更具可讀性和可維護性,減少出錯的概率。
全局變量的標志位變量命名時,應該遵循一些具體的規則,以確保代碼的可讀性和易維護性。以下是一些建議:
-
使用前綴標識全局變量:
- 以
g_
前綴來標識全局變量。例如:g_flag_connected
,g_flag_initialized
。
- 以
-
清晰描述變量含義:
- 變量名應反映其用途或含義。使用描述性單詞使其一目了然。例如:
g_flag_error_occurred
,g_flag_data_ready
。
- 變量名應反映其用途或含義。使用描述性單詞使其一目了然。例如:
-
使用布爾命名約定:
- 對于布爾類型的標志位變量,使用
is
,has
,can
等前綴。例如:g_is_connected
,g_has_error
,g_can_read
。
- 對于布爾類型的標志位變量,使用
-
統一命名風格:
- 保持命名的一致性,確保團隊中所有開發者遵循相同的命名規范。例如:所有標志位變量都以
g_flag_
開頭,然后描述具體含義。
- 保持命名的一致性,確保團隊中所有開發者遵循相同的命名規范。例如:所有標志位變量都以
-
避免使用縮寫:
- 除非是非常常見和容易理解的縮寫,否則盡量避免使用縮寫,以防止誤解。例如:
g_flag_buffer_overflow
而不是g_flag_buf_ovf
。
- 除非是非常常見和容易理解的縮寫,否則盡量避免使用縮寫,以防止誤解。例如:
-
示例命名:
g_flag_initialized
- 表示系統或模塊是否已初始化。g_flag_error_occurred
- 表示是否發生了錯誤。g_flag_data_ready
- 表示數據是否已經準備好。g_is_connected
- 表示是否已經連接。g_has_data
- 表示是否有數據可用。
通過遵守這些命名規則,可以使代碼更具可讀性和一致性,方便團隊協作和代碼維護。
在單片機開發中,良好的編程習慣和命名規則可以極大地提高代碼的可讀性、可維護性和可靠性。以下是一些值得學習和遵守的編程習慣和命名規則:
編程習慣
-
注釋代碼:
- 在代碼中添加必要的注釋,解釋代碼的功能、邏輯和重要的變量或函數。確保注釋清晰且有意義。
-
模塊化編程:
- 將代碼劃分為多個模塊或文件,每個模塊負責特定的功能。這樣可以提高代碼的可維護性和可復用性。
-
使用常量和宏定義:
- 使用
#define
或const
定義常量,避免在代碼中使用硬編碼的數值。例如:#define MAX_BUFFER_SIZE 1024
。
- 使用
-
初始化所有變量:
- 在使用變量之前進行初始化,以防止未定義行為和潛在的錯誤。
-
防御性編程:
- 編寫健壯的代碼,處理所有可能的錯誤情況和異常情況。使用斷言(assert)來捕捉不應出現的條件。
-
合理使用中斷:
- 中斷服務程序(ISR)應該盡量短小精悍,避免在ISR中執行耗時操作。將復雜的處理移到主程序中完成。
-
遵循代碼規范:
- 遵循團隊或項目的編碼規范,確保代碼風格一致。常見的編碼規范包括命名規則、縮進風格、括號位置等。
命名規則
-
變量命名:
- 使用描述性名稱,避免使用單個字符或無意義的名稱。變量名應反映其用途或含義。
- 使用小寫字母,單詞之間用下劃線分隔。例如:
sensor_value
,motor_speed
。
-
常量命名:
- 使用全大寫字母,單詞之間用下劃線分隔。例如:
MAX_BUFFER_SIZE
,PI_VALUE
。
- 使用全大寫字母,單詞之間用下劃線分隔。例如:
-
函數命名:
- 使用動詞或動詞短語開頭,后接名詞,單詞之間用下劃線分隔。例如:
init_motor
,read_sensor_value
。
- 使用動詞或動詞短語開頭,后接名詞,單詞之間用下劃線分隔。例如:
-
結構體和枚舉命名:
- 結構體和枚舉類型名使用大寫字母開頭,每個單詞的首字母大寫,例如:
SensorData
,ErrorCode
。 - 結構體變量名使用小寫字母,單詞之間用下劃線分隔,例如:
sensor_data
,error_code
。
- 結構體和枚舉類型名使用大寫字母開頭,每個單詞的首字母大寫,例如:
-
宏定義命名:
- 使用全大寫字母,單詞之間用下劃線分隔。例如:
#define LED_PIN 13
,#define TIMER_PERIOD 1000
。
- 使用全大寫字母,單詞之間用下劃線分隔。例如:
-
文件命名:
- 文件名應簡潔且具有描述性,通常使用小寫字母,單詞之間用下劃線分隔,例如:
main.c
,sensor_driver.h
。
- 文件名應簡潔且具有描述性,通常使用小寫字母,單詞之間用下劃線分隔,例如:
代碼示例
// 常量和宏定義
#define MAX_BUFFER_SIZE 1024
#define LED_PIN 13// 結構體定義
typedef struct {int sensor_value;float temperature;
} SensorData;// 函數聲明
void init_motor(void);
int read_sensor_value(void);// 主函數
int main(void) {// 變量初始化SensorData sensor_data = {0, 0.0};int sensor_value = 0;// 初始化電機init_motor();// 讀取傳感器值sensor_value = read_sensor_value();// 處理傳感器數據sensor_data.sensor_value = sensor_value;sensor_data.temperature = sensor_value * 0.1;return 0;
}// 函數定義
void init_motor(void) {// 初始化電機的代碼
}int read_sensor_value(void) {// 讀取傳感器值的代碼return 42;
}
這些編程習慣和命名規則可以幫助你編寫更高質量、更易維護的代碼,尤其是在團隊協作和長期維護中顯得尤為重要。
在編程中,斷言(assert)是一種用于捕捉不應出現的條件的調試工具。斷言可以在開發和調試過程中幫助檢測程序中的邏輯錯誤和不一致性。當程序運行時,如果斷言條件為假(false),程序會立即終止,并輸出錯誤信息,方便開發者定位和修復問題。
使用斷言的步驟
-
包含頭文件:
- 使用斷言前,需要包含頭文件
<assert.h>
。
- 使用斷言前,需要包含頭文件
-
使用
assert
宏:- 使用
assert
宏來檢查條件。語法如下:#include <assert.h>void some_function(int value) {assert(value > 0); // 如果 value <= 0,程序將終止并輸出錯誤信息 }
- 使用
-
編譯時控制:
- 斷言在調試階段非常有用,但在發布階段可能不需要。可以通過定義
NDEBUG
來禁用斷言。#define NDEBUG #include <assert.h>
- 斷言在調試階段非常有用,但在發布階段可能不需要。可以通過定義
示例代碼
以下是一個使用斷言的示例代碼:
#include <assert.h>
#include <stdio.h>// 計算數組中元素的平均值
double calculate_average(int *array, int size) {// 斷言數組指針不為空assert(array != NULL);// 斷言數組大小大于0assert(size > 0);int sum = 0;for (int i = 0; i < size; i++) {sum += array[i];}return (double)sum / size;
}int main() {int values[] = {10, 20, 30, 40, 50};int size = sizeof(values) / sizeof(values[0]);// 調用函數前的斷言assert(size > 0);double average = calculate_average(values, size);printf("Average: %.2f\n", average);return 0;
}
解釋
-
包含頭文件:
- 代碼中首先包含了
<assert.h>
頭文件,這個頭文件定義了assert
宏。
- 代碼中首先包含了
-
使用
assert
宏:- 在
calculate_average
函數中,使用了兩個斷言來確保輸入的數組指針不為空且數組大小大于0。 - 在
main
函數中,使用了一個斷言來確保數組大小大于0。
- 在
-
斷言失敗:
- 如果
assert
條件為假,程序將終止并輸出錯誤信息,包括斷言失敗的條件和源代碼文件中的行號。
- 如果
禁用斷言
在發布階段,可以通過定義 NDEBUG
來禁用斷言。例如:
#define NDEBUG
#include <assert.h>
在定義 NDEBUG
后,所有 assert
語句將被預處理器移除,斷言檢查將不會在程序運行時執行。
總結
使用斷言可以有效地捕捉程序中不應出現的條件,幫助開發者在調試階段快速定位和修復邏輯錯誤。通過合理使用斷言,可以提高代碼的健壯性和可靠性。在發布階段,可以通過定義 NDEBUG
來禁用斷言,確保程序的性能和穩定性。
在項目中使用單片機的多個串口(如串口0、串口1、串口2)進行數據收發時,可以使用結構體來組織相關的變量,以便管理和操作這些串口。以下是一個示例,定義了一個結構體來表示三個串口的相關變量:
typedef struct {// 串口0相關變量volatile uint8_t uart0_rx_buffer[UART_RX_BUFFER_SIZE];volatile uint8_t uart0_tx_buffer[UART_TX_BUFFER_SIZE];volatile uint8_t uart0_rx_index;volatile uint8_t uart0_tx_index;volatile bool uart0_rx_complete;// 串口1相關變量volatile uint8_t uart1_rx_buffer[UART_RX_BUFFER_SIZE];volatile uint8_t uart1_tx_buffer[UART_TX_BUFFER_SIZE];volatile uint8_t uart1_rx_index;volatile uint8_t uart1_tx_index;volatile bool uart1_rx_complete;// 串口2相關變量volatile uint8_t uart2_rx_buffer[UART_RX_BUFFER_SIZE];volatile uint8_t uart2_tx_buffer[UART_TX_BUFFER_SIZE];volatile uint8_t uart2_rx_index;volatile uint8_t uart2_tx_index;volatile bool uart2_rx_complete;
} SerialPorts;// 定義一個實例化的結構體變量
SerialPorts serial_ports;
結構體成員說明:
- uartX_rx_buffer: 串口X接收緩沖區,用于存儲從串口X接收到的數據。
- uartX_tx_buffer: 串口X發送緩沖區,用于存儲待發送至串口X的數據。
- uartX_rx_index: 串口X接收緩沖區的索引,指示下一個接收數據的位置。
- uartX_tx_index: 串口X發送緩沖區的索引,指示下一個發送數據的位置。
- uartX_rx_complete: 串口X接收完成標志,用于指示是否完成了一次數據接收。
注意事項:
-
volatile 關鍵字:
- 在單片機編程中,通常使用
volatile
關鍵字來聲明這些變量,以確保編譯器不會對它們進行優化,保證每次訪問都是直接從內存中讀取或寫入。
- 在單片機編程中,通常使用
-
緩沖區大小定義:
UART_RX_BUFFER_SIZE
和UART_TX_BUFFER_SIZE
是根據實際需求定義的宏或常量,表示串口接收和發送緩沖區的大小。
-
多個串口的區分:
- 結構體中通過命名方式區分不同的串口變量,如
uart0_...
、uart1_...
、uart2_...
。
- 結構體中通過命名方式區分不同的串口變量,如
通過這種方式,你可以方便地管理和操作多個串口的數據收發,使代碼結構更清晰,易于維護和擴展。