本文介紹何謂##運算子,並且引用TI C2000微處理器的公開範例PMBus communication stack說明這個預編譯器所使用的符號,目的是將兩個token組合成一個新字符。與巨集相似,會在實際編譯前先對原始碼進行處理,之後才依序進行連結、組合。{alertInfo}
目錄
前言
在TI原廠提供的PMBus範例*中,有一個巨集令我印象深刻,在每個PMBus target handler之前都有一串 PMBUS_STACK_FILENUM(N),用法就像pmbus_status_config.c中的方式,在每個獨立function前新增一句。PMBus範例
File: pmbus_state_config.c
#ifndef PMBUS_OVER_I2C
//
// Includes
//
#include "stdint .h"
#include "stdbool .h"
#include "pmbus_stack_config.h"
//
// Defines
//
PMBUS_STACK_FILENUM(1)
#define PMBUS_STACK_TARGET_ADDRESS 0U
#define PMBUS_STACK_TARGET_MASK 0x7FU
//
// Globals
//
PMBus_StackObject PMBusStackTarget;
PMBus_StackHandle PMBusStackTargetHandle = &PMBusStackTarget;
//***************************************************************************
//
// PMBusStack_initModule
//
//***************************************************************************
bool PMBusStack_initModule(PMBus_StackHandle handle, const uint32_t moduleBase,
uint16_t *buffer)
{
點開位於pmbus_stack_assert.h 發現巨集宣告可以展開成
//! Assign a "unique" number to each file, compiler error
//! on duplicates
#define PMBUS_STACK_FILENUM(number) \
enum{FILE_NUM = number}; \
void _nullFunction##number(void){}
##運算子說明
從字面上看,這個巨集為每個檔案宣告不同ID,當ID重複時編譯器會報錯。這樣做的意義推測是避免重複宣告。
但這裡頭用到##運算子,因為出現的機率實在是太少,網路搜尋了一波,發現是預編譯器語法的一種 token-pasting operator 。
他會把原本function中呼叫的第一個與第二個參數(token)做合併,要注意不是把變數家再一起,而是直接把原始碼中的字串做合併。
舉例來說,有一個cancat函數使用a與b兩個參數(token)
先不管它實際上在做什麼,我們定義concat(a,b) a##b 會把source
code中所有concat(a,b)直接轉換成ab字串
#include "stdio.h"
#define concat(a, b) a##b
int main(void)
{
int xy = 30;
printf("%d", concat(x, y));
return 0;
}
因此,以上程式碼再經過預編譯(pre-conpile)後會變成:
#include "stdio.h"
#define concat(a, b) a##b
int main(void)
{
int xy = 30;
printf("%d", ab);
return 0;
}
總結
回到pmbus的範例,number是被PMBUS_STACK_FILENUM 調用的token,所以下面
void _nullFunction##number(void){}
經過預編譯器會變成void _nullFunctionnumber(void){}
舉例來說 PMBUS_STACK_FILENUM(1)會變成
void _nullFunction1(void){}
以上是研究PMBus Driverlib 的一些小發現
參考資料
*範例位/ti/c2000/C2000Ware_4_03_00_00/libraries/communications/PMBus/c28/pmbus_stack_project
*巨集位於/ti/c2000/C2000Ware_4_03_00_00/libraries/communications/PMBus/c28/include/
pmbus_stack_assert.h
張貼留言
留個言吧