日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言余数为0输出intact,C语言中的宏是怎么展开的?

發布時間:2024/3/24 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言余数为0输出intact,C语言中的宏是怎么展开的? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

展開流程偽碼:(自己總結的,不一定對)

//loop:

//將實參代入文本中

//if 在某個實參之前有符號“#”(字符串化)或“##”(連接)then

// ? ?對當前的文本做一次字符串化或者連接

//

// ? ?if 結果是另外一個宏名 then

// ? ? ? ?替換一次

// ? ?end

//

// ? ?結束當前的處理

//else

// ? ?foreach 實參 do

// ? ? ? ?if 是宏 then

// ? ? ? ? ? ?goto loop

// ? ? ? ?end

// ? ?end

//

// ? ?if 文本中不包含任何宏 then

// ? ? ? ?if 結果是另外一個宏名 then

// ? ? ? ? ? ?替換一次

// ? ? ? ?end

//

// ? ? ? ?結束全部處理

// ? ?else

// ? ? ? ?goto loop

// ? ?end

//end

示例:

#include

using namespace std;

#define to_str(x) #x // 稱【#x】為文本,稱【x】為形參

#define macro_expansion(m) to_str(m)

#define token_cat(x, y) x##y

#define token_cat_ex(x, y) token_cat(x, y)

#define max(a, b) ((a) > (b) ? (a) : (b))

#define ab token_cat(1, 2)

int main(int argc, char* argv[])

{

cout << to_str(token_cat(1, 2)) << endl; // token_cat(1, 2)

// 代入實參=> #token_cat(1, 2)

// 實參之前有符號##,對當前文本做一次連接,然后結束當前的處理=> "token_cat(1, 2)"

cout << macro_expansion(to_str(token_cat(1, 2))) << endl; // "token_cat(1, 2)"

// 代入實參=> to_str(to_str(token_cat(1, 2)))

// 實參是宏,對實參做處理(這是當前處理),代入其實參=> to_str(#token_cat(1, 2))

// 當前處理中,實參之前有符號#,對當前文本做一次字符串化,然后結束當前的處理=> to_str("token_cat(1, 2)")

// 實參處理已完成,最外層還是一個宏,代入實參(注意當前處理變了)=> #"token_cat(1, 2)"

// 實參之前有符號#,對當前文本做一次字符串化,然后結束當前的處理=> "\"token_cat(1, 2)\""

cout << macro_expansion(token_cat(token_cat(1, 2), 3)) << endl; // token_cat(1, 2)3

// 代入實參=> to_str(token_cat(token_cat(1, 2), 3))

// 實參是宏,對實參做處理(這是當前處理),代入其實參=> to_str(token_cat(1, 2)##3))

// 當前處理中,實參之前有符號##,對當前文本做一次連接,然后結束當前的處理=> to_str(token_cat(1, 2)3))

// 實參處理已完成,最外層還是一個宏,代入實參(注意當前處理變了)=> #token_cat(1, 2)3)

// 實參之前有符號##,對當前文本做一次連接,然后結束當前的處理=> "token_cat(1, 2)3)"

cout << macro_expansion(token_cat_ex(token_cat_ex(1, 2), 3)) << endl; // 123

// 代入實參=> to_str(token_cat_ex(token_cat_ex(1, 2), 3))

// 實參是宏,對實參做處理(這是當前處理),代入其實參=> to_str(token_cat(token_cat_ex(1, 2), 3))

// 第二次代入實參后,第一個實參仍然是宏,繼續代入=> to_str(token_cat(token_cat(1, 2), 3))

// 第一個實參仍然是宏,繼續代入=> to_str(token_cat(1##2, 3))

// 連接第一個實參,至此第一個實參處理完成=> to_str(token_cat(12, 3))

// 后面的實參不是宏,為上層的宏代入實參=> to_str(12#3)

// 連接一次=> to_str(123)

// 全部實參處理完成,最外層還是一個宏,代入實參=> #123

// 實參之前有符號#,對當前文本做一次字符串化,然后結束當前的處理=> "123"

int n = max(1, 2);

// 代入實參=> ((1) > (2) ? (1) : (2))

// 文本中不包含任何宏,結束全部處理

cout << macro_expansion(max(1, 2)) << endl; // ((1) > (2) ? (1) : (2))

// 代入實參=> to_str(max(1, 2))

// 實參是宏,對實參做處理(這是當前處理),代入其實參=> to_str(((1) > (2) ? (1) : (2)))

// 實參處理完了,文本中還包含一個宏,代入實參=> #((1) > (2) ? (1) : (2))

// 實參之前有符號#,對當前文本做一次字符串化,然后結束當前的處理=> "((1) > (2) ? (1) : (2))"

cout << macro_expansion(token_cat(a, b)) << endl; // token_cat(1, 2)

// 代入實參=> to_str(token_cat(a, b))

// 實參是宏,對實參做處理(這是當前處理),代入其實參=> to_str(a##b)

// 當前處理中,實參之前有符號##,對當前文本做一次連接,然后結束當前的處理=> to_str(ab)

// ab是另外一個宏的名字,替換一次,注意只替換一次=> to_str(token_cat(1, 2))

// 實參處理已完成,最外層還是一個宏,代入實參(注意當前處理變了)=> #token_cat(1, 2)

// 實參之前有符號#,對當前文本做一次字符串化,然后結束當前的處理=> "token_cat(1, 2)"

return 0;

}

我自己的一些使用

#define TOKEN_CAT(x, y) x##y

//AUX_OSS_ACTORID(rstOssExploreSecret, ActorID, m_poPetOnDuty->GetExclusiveItemID());

// 參數:日志消息體,字段名,程序中的Actor ID對象

#define AUX_OSS_ACTORID(x, y, z)\

do {\

x.TOKEN_CAT(y, _Sid) = z.uSid;\

x.TOKEN_CAT(y, _ZoneID) = z.uZoneID;\

} while (0)

//AUX_OSS_THING_GUID(rstOssExploreSecret, PetGUID, m_poPetOnDuty->GetExclusiveItemID());

// 參數:日志消息體,字段名,程序中的GUID對象

#define AUX_OSS_THING_GUID(x, y, z) \

do {\

unsigned int* apu32GUIDField[4] = {\

&TOKEN_CAT(TOKEN_CAT(x, .), TOKEN_CAT(y, _Time)),\

&TOKEN_CAT(TOKEN_CAT(x, .), TOKEN_CAT(y, _Reserve)),\

&TOKEN_CAT(TOKEN_CAT(x, .), TOKEN_CAT(y, _Seq)),\

&TOKEN_CAT(TOKEN_CAT(x, .), TOKEN_CAT(y, _SrvID))\

};\

*apu32GUIDField[0] = (z).dwTime;\

*apu32GUIDField[1] = (z).dwReserve;\

*apu32GUIDField[2] = (z).dwSeq;\

*apu32GUIDField[3] = (z).dwSrvID;\

} while (0)

struct TRewardGroup

{

int m_i32RewardGroupID;

float m_f32Prop;

int m_i32BindMark;

int m_i32OutputMode;

};

#define REWARD_GROUP(_pstCfg, i) {TOKEN_CAT(TOKEN_CAT(_pstCfg, ->), TOKEN_CAT(iRewardGroupID, i)),\

TOKEN_CAT(TOKEN_CAT(_pstCfg, ->), TOKEN_CAT(iProp, i)) / reward_group_rate_base, \

TOKEN_CAT(TOKEN_CAT(_pstCfg, ->), TOKEN_CAT(iBindMark, i)), \

TOKEN_CAT(TOKEN_CAT(_pstCfg, ->), TOKEN_CAT(iOutputMode, i))}

TRewardGroup astDynamicRewardGroup[] = {

REWARD_GROUP(pstDynamicOutputGoods, 1), REWARD_GROUP(pstDynamicOutputGoods, 2),

REWARD_GROUP(pstDynamicOutputGoods, 3), REWARD_GROUP(pstDynamicOutputGoods, 4),

REWARD_GROUP(pstDynamicOutputGoods, 5), REWARD_GROUP(pstDynamicOutputGoods, 6),

REWARD_GROUP(pstDynamicOutputGoods, 7), REWARD_GROUP(pstDynamicOutputGoods, 8),

REWARD_GROUP(pstDynamicOutputGoods, 9), REWARD_GROUP(pstDynamicOutputGoods, 10)

};

struct TRewardGoods

{

int m_i32RewardItemID;

int m_i32RewardItemCount;

int m_i32RewardItemBind;

};

#define REWARD_GOODS(i) {pstRewardCfg->TOKEN_CAT(iRewardItemID, i), \

pstRewardCfg->TOKEN_CAT(iRewardItemCount, i), \

pstRewardCfg->TOKEN_CAT(iRewardItemBind, i)}

TRewardGoods astRewardGoods[] = {

REWARD_GOODS(1), REWARD_GOODS(2), REWARD_GOODS(3)

};

下面一篇文章http://www.boost.org/doc/libs/1_37_0/libs/wave/doc/macro_expansion_process.html

The Macro Expansion Process

The macro expansion process described here was initially developed by?Paul Mensonides?and is implemented in?Wave. It is much more understandable as the description of the desired macro expansion algorithm provided in the C++ Standard?[1].

Macro replacement proceeds left-to-right.

If, during scanning (or rescanning) an identifier is found, it is looked up in the symbol table. If the identifier is not found in the symbol table, it is not a macro and scanning continues.

If the identifier is found, the value of a flag associated with the identifier is used to determine if the identifier is available for expansion. If it is not, the specific token (i.e. the specific instance of the identifier) is marked as disabled and is not expanded. If the identifier is available for expansion, the value of a different flag associated with the identifier in the symbol table is used to determine if the identifier is an object-like or function-like macro. If it is an object-like macro, it is expanded. If it is a function-like macro, it is only expanded if the next token is an left parenthesis.

An identifier is available for expansion if it is not marked as disabled and if the the value of the flag associated with the identifier is not set, which is used to determine if the identifier is available for expansion.

(If a macro is an object-like macro, skip past the next two paragraphs.)

If a macro to be expanded is a function-like macro, it must have the exact number of actual arguments as the number of formal parameters required by the definition of the macro. Each argument is recursively scanned and expanded. Each parameter name found in the replacement list is replaced by the expanded actual argument after leading and trailing whitespace and all placeholder tokens are removed unless the parameter name immediately follows the stringizing operator ('#') or is adjacent to the token-pasting operator ('##').

If the parameter name immediately follows the stringizing operator ('#'), a stringized version of the unexpanded actual argument is inserted. If the parameter name is adjacent to the token-pasting operator ('##'), the unexpanded actual argument is inserted after all placeholder tokens are removed.

All concatenation takes place in the replacement list. (If a single concatenation yields multiple tokens, the behavior is undefined. Moreover,?Wave?in normal C++98 and C99 modes issues an error, if more then one token is produced as the result of the concatenation. In C++0x mode?Wave?treats token-pasting of unrelated tokens as well defined and inserts the reparsed string representation of the concatenated tokens into the replacement list.).

The flag in the symbol table entry associated with the name of the macro being expanded is set to indicate the that the macro is not available for expansion.

The replacement list is rescanned for further macro expansion. All leading and trailing whitespace tokens in the replacement list are removed (the placeholder tokens are left intact).

After rescanning completes, the flag in the symbol table entry associated with the name of macro being expanded is cleared to indicate that the macro is again available for expansion, and the sequence of tokens that constitutes the rescanned replacement list is returned to the point of invocation of the macro.

If this sequence of tokens is empty, it is replaced by a placeholder token. If a placeholder is found during scanning (or rescanning) it is ignored. (Also, if the only thing separating a parameter from the stringizing operator or token-pasting operator is placeholder, it is also ignored in that context.)

This sequence of tokens is inserted at the original point that the macro was invoked, and scanning continues starting with the last token of the newly inserted sequence of tokens. I.e. scanning looks back a single token (possibly a placeholder token) and continues.

總結

以上是生活随笔為你收集整理的C语言余数为0输出intact,C语言中的宏是怎么展开的?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。