C語言#和##連接符在項目中的應用(漂亮)
之前看見ST官方一個老外的風格,看完之后大贊。看看他是怎么寫的:
#ifndef RINGBUFF_HDR_H
#define RINGBUFF_HDR_H
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include <stdint.h>
/**
* \defgroup RINGBUFF Ring buffer
* \brief Generic ring buffer manager
* \{
*/
/* --- Buffer unique part starts --- */
/**
* \brief Buffer function/typedef prefix string
*
* It is used to change function names in zero time to easily re-use same library between applications.
* Use `#define BUF_PREF(x) my_prefix_ ## x` to change all function names to (for example) `my_prefix_buff_init`
*
* \note Modification of this macro must be done in header and source file aswell
*/
#define BUF_PREF(x) ring ## x
/* --- Buffer unique part ends --- */
/**
* \brief Buffer structure
*/
typedef struct {
uint8_t* buff; /*!< Pointer to buffer data.
Buffer is considered initialized when `buff != NULL` and `size` */
size_t size; /*!< Size of buffer data. Size of actual buffer is `1` byte less than value holds */
size_t r; /*!< Next read pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */
size_t w; /*!< Next write pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */
} BUF_PREF(buff_t);
uint8_t BUF_PREF(buff_init)(BUF_PREF(buff_t)* buff, void* buffdata, size_t size);
void BUF_PREF(buff_free)(BUF_PREF(buff_t)* buff);
void BUF_PREF(buff_reset)(BUF_PREF(buff_t)* buff);
/* Read/Write functions */
size_t BUF_PREF(buff_write)(BUF_PREF(buff_t)* buff, const void* data, size_t btw);
size_t BUF_PREF(buff_read)(BUF_PREF(buff_t)* buff, void* data, size_t btr);
size_t BUF_PREF(buff_peek)(BUF_PREF(buff_t)* buff, size_t skip_count, void* data, size_t btp);
/* Buffer size information */
size_t BUF_PREF(buff_get_free)(BUF_PREF(buff_t)* buff);
size_t BUF_PREF(buff_get_full)(BUF_PREF(buff_t)* buff);
/* Read data block management */
void * BUF_PREF(buff_get_linear_block_read_address)(BUF_PREF(buff_t)* buff);
size_t BUF_PREF(buff_get_linear_block_read_length)(BUF_PREF(buff_t)* buff);
size_t BUF_PREF(buff_skip)(BUF_PREF(buff_t)* buff, size_t len);
/* Write data block management */
void * BUF_PREF(buff_get_linear_block_write_address)(BUF_PREF(buff_t)* buff);
size_t BUF_PREF(buff_get_linear_block_write_length)(BUF_PREF(buff_t)* buff);
size_t BUF_PREF(buff_advance)(BUF_PREF(buff_t)* buff, size_t len);
#undef BUF_PREF /* Prefix not needed anymore */
/**
* \}
*/
#ifdef __cplusplus
}
#endif
#endif /* RINGBUFF_HDR_H */
這個老外實現(xiàn)的是一個環(huán)形緩沖,然而他巧妙的將ring這個字串去掉,最后閱讀代碼看到的是非常整齊的:
BUF_PREF(buffer_init)
BUF_PREF(buff_free)
BUF_PREF(buff_write)
BUF_PREF(buff_read)
等等。。。
接下來看看到底是怎么用的:
#define BUF_PREF(x) ring ## x
"##" 表示將左邊的字符串和右邊的字符串連接起來,但是只能黏貼C語言除了關鍵字以外的合法標識符 于是上面展開的效果如下:
ring_buffer_init
ring_buffer_free
ring_buffer_write
ring_buffer_read
等等。。。
既然知道了原理,那我在項目上可以這么來用。
之前,你寫個LED驅動或者別的可能是這樣的,定義了這么多個函數(shù)
void led_device_open(void);
void led_device_close(void);
uint8_t led_device_read(void);
uint8_t led_device_write(uint8_t status);
。。。
看起來很統(tǒng)一,我一眼看出這是一個LED的操作方法,但操作一個LED不就是open,close,read,write方法嗎?
我們可以讓它看起來更優(yōu)雅:
#define LED_CLASS(x) led_device_ ## x
void LED_CLASS(open)(void);
void LED_CLASS(close)(void);
uint8_t LED_CLASS(read)(void);
uint8_t LED_CLASS(write)(uint8_t status);
如果我寫另外一個驅動,也是一樣有open,close,read,write接口,假設是個FLASH設備。那還是一樣的:
#define FLASH_CLASS(x) flash_device_ ## x
void FLASH_CLASS(open)(void);
void FLASH_CLASS(close)(void);
uint8_t FLASH_CLASS(read)(void);
uint8_t FLASH_CLASS(write)(uint8_t status);
看起來舒服多了!Good!
那么##和#又有什么區(qū)別呢?
##剛剛已經(jīng)說了,是黏貼字符串
而#表示的是將參數(shù)轉換為字符串
下面寫一個跟#相關的例子:
#include <stdio.h>
#define Print(x) printf("%s %d\n",#x,x);
int main(void)
{
Print(100);
return 0 ;
}
運行結果:
公眾號粉絲福利時刻
這里我給大家申請到了福利,本公眾號讀者購買小熊派開發(fā)板可享受9折優(yōu)惠,有需要購買小熊派的朋友,淘寶搜索即可,跟客戶說你是公眾號:嵌入式云IOT技術圈 的粉絲,立享9折優(yōu)惠!
往期精彩
C語言字符串的另類用法
別瞎找了,你要的C語言經(jīng)典示例都在這~
C語言表驅動法編程實踐(精華帖,建議收藏并實踐)
嵌入式C語言代碼優(yōu)化方案(深度好文,建議花時間研讀并收藏)
若覺得本次分享的文章對您有幫助,隨手點[在看]
并轉發(fā)分享,也是對我的支持。
免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!