Académique Documents
Professionnel Documents
Culture Documents
cWhataretheapplicationsofthe##preprocessoroperatorandgotchastoconsider?StackOverflow
signup
login
tour
help
xDismiss
JointheStackOverflowCommunity
Stack Overflow is a community of 6.4 million
programmers, just like you, helping each other.
Join them it only takes a minute:
Signup
Whataretheapplicationsofthe##preprocessoroperatorandgotchastoconsider?
Asmentionedinmanyofmypreviousquestions,I'mworkingthroughK&R,andamcurrentlyintothepreprocessor.Oneofthemoreinteresting
thingssomethingIneverknewbeforefromanyofmypriorattemptstolearnCisthe ## preprocessoroperator.AccordingtoK&R:
Thepreprocessoroperator ## providesawaytoconcatenateactualargumentsduringmacroexpansion.Ifaparameterinthereplacement
textisadjacenttoa ## ,theparameterisreplacedbytheactualargument,the ## andsurroundingwhitespaceareremoved,andtheresult
isrescanned.Forexample,themacro paste concatenatesitstwoarguments:
#definepaste(front,back)front##back
so
paste(name,1)
createsthetoken
name1
Howandwhywouldsomeoneusethisintherealworld?Whatarepracticalexamplesofitsuse,andaretheregotchastoconsider?
c cpreprocessor kernighanandritchie stringification
editedFeb9at10:30
askedOct19'08at19:51
Lundin
62.8k
JohnRudy
13
89
167
20.9k
10
52
95
13Answers
CrashRpt:Using##toconvertmacromultibytestringstoUnicode
AninterestingusageinCrashRpt(crashreportinglibrary)isthefollowing:
#defineWIDEN2(x)L##x
#defineWIDEN(x)WIDEN2(x)
//NoteyouneedaWIDEN2sothat__DATE__willevaluatefirst.
Heretheywanttouseatwobytestringinsteadofaonebytepercharstring.Thisprobablylooks
likeitisreallypointless,buttheydoitforagoodreason.
std::wstringBuildDate=std::wstring(WIDEN(__DATE__))+L""+WIDEN(__TIME__);
Theyuseitwithanothermacrothatreturnsastringwiththedateandtime.
Putting
nexttoa
__DATE__
wouldgiveyouacompilingerror.
Windows:Using##forgenericUnicodeormultibytestrings
Windowsusessomethinglikethefollowing:
#ifdef_UNICODE
#define_T(x)L##x
#else
#define_T(x)x
#endif
http://stackoverflow.com/questions/216875/whataretheapplicationsofthepreprocessoroperatorandgotchastoconside
1/6
12/3/2016
And
_T
cWhataretheapplicationsofthe##preprocessoroperatorandgotchastoconsider?StackOverflow
isusedeverywhereincode
Variouslibraries,usingforcleanaccessorandmodifiernames:
I'vealsoseenitusedincodetodefineaccessorsandmodifiers:
#defineMYLIB_ACCESSOR(name)(Get##name)
#defineMYLIB_MODIFIER(name)(Set##name)
Likewiseyoucanusethissamemethodforanyothertypesofclevernamecreation.
Variouslibraries,usingittomakeseveralvariabledeclarationsatonce:
#defineCREATE_3_VARS(name)name##1,name##2,name##3
intCREATE_3_VARS(myInts);
myInts1=13;
myInts2=19;
myInts3=77;
editedFeb4at18:27
answeredOct19'08at19:58
PeterMortensen
10.4k
13
72
BrianR.Bondy
108
201k
82
478
574
3 Sinceyoucanconcatenatestringliteralsatcompiletime,youcouldreducetheBuildDateexpressionto
std::wstringBuildDate=WIDEN(__DATE__)L""WIDEN(__TIME__); andimplicitlybuildthewhole
stringatonce.user666412Feb15at17:54
Theoutput:
buggyresults:
SOME_MACRO__LINE__
BAD_PASTE(SOME_MACRO,__LINE__)
PASTE(SOME_MACRO,__LINE__)
desiredresult:
function_name21
answeredOct19'08at23:49
MichaelBurr
243k
31
364
580
1 Foranexplanationofthispreprocessorbehavior,seestackoverflow.com/questions/8231966/
AdamDavis Dec1'11at20:50
@MichaelBurriwasreadingyouranswer&ihaveadoubt.Howcomethis LINEisprintingthelinenumber?
HELPPLZJun26'14at16:51
2 @AbhimanyuAryan:I'mnotsureifthisiswhatyou'reasking,but __LINE__ isaspecialmacronamethat
isreplacedbythepreprocessorwiththecurrentlinenumberofthesourcefile.MichaelBurrJun26'14at
http://stackoverflow.com/questions/216875/whataretheapplicationsofthepreprocessoroperatorandgotchastoconside
2/6
12/3/2016
cWhataretheapplicationsofthe##preprocessoroperatorandgotchastoconsider?StackOverflow
19:16
Here'sagotchathatIranintowhenupgradingtoanewversionofacompiler:
Unnecessaryuseofthetokenpastingoperator(
undesiredwhitespace,warnings,orerrors.
##
)isnonportableandmaygenerate
Whentheresultofthetokenpastingoperatorisnotavalidpreprocessortoken,thetokenpasting
operatorisunnecessaryandpossiblyharmful.
Forexample,onemighttrytobuildstringliteralsatcompiletimeusingthetokenpastingoperator:
#defineSTRINGIFY(x)#x
#definePLUS(a,b)STRINGIFY(a##+##b)
#defineNS(a,b)STRINGIFY(a##::##b)
printf("%s%s\n",PLUS(1,2),NS(std,vector));
Onsomecompilers,thiswilloutputtheexpectedresult:
1+2std::vector
Onothercompilers,thiswillincludeundesiredwhitespace:
1+2std::vector
FairlymodernversionsofGCC(>=3.3orso)willfailtocompilethiscode:
foo.cpp:16:1:pasting"1"and"+"doesnotgiveavalidpreprocessingtoken
foo.cpp:16:1:pasting"+"and"2"doesnotgiveavalidpreprocessingtoken
foo.cpp:16:1:pasting"std"and"::"doesnotgiveavalidpreprocessingtoken
foo.cpp:16:1:pasting"::"and"vector"doesnotgiveavalidpreprocessingtoken
Thesolutionistoomitthetokenpastingoperatorwhenconcatenatingpreprocessortokensto
C/C++operators:
#defineSTRINGIFY(x)#x
#definePLUS(a,b)STRINGIFY(a+b)
#defineNS(a,b)STRINGIFY(a::b)
printf("%s%s\n",PLUS(1,2),NS(std,vector));
TheGCCCPPdocumentationchapteronconcatenationhasmoreusefulinformationonthe
tokenpastingoperator.
answeredOct19'08at21:08
bk1e
18.3k
37
60
ThanksIwasn'tawareofthis(butthenIdon'tusethesepreprocessingoperatorstoomuch...).
MichaelBurrOct20'08at1:12
3 It'scalledthe"tokenpasting"operatorforareasontheintentistoendupwithasingletokenwhenyou're
done.Nicewriteup.MarkRansomApr30'09at18:17
Whentheresultofthetokenpastingoperatorisnotavalidpreprocessortoken,thebehaviorisundefined.
Alek Jun30'14at15:19
Languagechangeslikehexadecimalfloats,or(inC++)digitseparatorsanduserdefinedliterals,continually
changewhatconstitutesa"validpreprocessingtoken",sopleaseneverabuseitlikethat!Ifyouhaveto
separate(languageproper)tokens,pleasespellthemastwoseparatetokens,anddon'trelyonaccidental
interactionsbetweenthepreprocessorgrammarandthelanguageproper.KerrekSBOct16at13:06
Thisisusefulinallkindsofsituationsinordernottorepeatyourselfneedlessly.Thefollowingis
anexamplefromtheEmacssourcecode.Wewouldliketoloadanumberoffunctionsfroma
library.Thefunction"foo"shouldbeassignedto fn_foo ,andsoon.Wedefinethefollowing
macro:
#defineLOAD_IMGLIB_FN(lib,func){\
fn_##func=(void*)GetProcAddress(lib,#func);\
if(!fn_##func)return0;\
}
Wecanthenuseit:
LOAD_IMGLIB_FN(library,XpmFreeAttributes);
LOAD_IMGLIB_FN(library,XpmCreateImageFromBuffer);
LOAD_IMGLIB_FN(library,XpmReadFileToImage);
LOAD_IMGLIB_FN(library,XImageFree);
http://stackoverflow.com/questions/216875/whataretheapplicationsofthepreprocessoroperatorandgotchastoconside
3/6
12/3/2016
cWhataretheapplicationsofthe##preprocessoroperatorandgotchastoconsider?StackOverflow
Thebenefitisnothavingtowriteboth
misspellingoneofthem).
fn_XpmFreeAttributes
and
"XpmFreeAttributes"
editedOct19'08at22:13
(andrisk
answeredOct19'08at20:09
VebjornLjosa
8,848
50
70
ApreviousquestiononStackOverflowaskedforasmoothmethodofgeneratingstring
representationsforenumerationconstantswithoutalotoferrorproneretyping.
Link
Myanswertothatquestionshowedhowapplyinglittlepreprocessormagicletsyoudefineyour
enumerationlikethis(forexample)...
ENUM_BEGIN(Color)
ENUM(RED),
ENUM(GREEN),
ENUM(BLUE)
ENUM_END(Color)
...Withthebenefitthatthemacroexpansionnotonlydefinestheenumeration(ina.hfile),italso
definesamatchingarrayofstrings(ina.cfile)
constchar*ColorStringTable[]=
{
"RED",
"GREEN",
"BLUE"
};
Thenameofthestringtablecomesfrompastingthemacroparameter(i.e.Color)toStringTable
usingthe##operator.Applications(tricks?)likethisarewherethe#and##operatorsare
invaluable.
editedFeb4at20:20
answeredOct19'08at22:41
PeterMortensen
10.4k
13
72
BillForster
108
4,050
15
23
Youcanusetokenpastingwhenyouneedtoconcatenatemacroparameterswith
somethingelse.
Itcanbeusedfortemplates:
#defineLINKED_LIST(A)structlist##_##A{\
Avalue;\
structlist##_##A*next;\
};
InthiscaseLINKED_LIST(int)wouldgiveyou
structlist_int{
intvalue;
structlist_int*next;
};
Similarlyyoucanwriteafunctiontemplateforlisttraversal.
editedFeb4at20:18
answeredOct19'08at20:09
PeterMortensen
10.4k
13
72
qrdl
108
23k
34
69
IuseitinCprogramstohelpcorrectlyenforcetheprototypesforasetofmethodsthatmust
conformtosomesortofcallingconvention.Inaway,thiscanbeusedforpoorman'sobject
orientationinstraightC:
SCREEN_HANDLER(activeCall)
expandstosomethinglikethis:
STATUSactiveCall_constructor(HANDLE*pInst)
STATUSactiveCall_eventHandler(HANDLE*pInst,TOKEN*pEvent);
STATUSactiveCall_destructor(HANDLE*pInst);
Thisenforcescorrectparameterizationforall"derived"objectswhenyoudo:
http://stackoverflow.com/questions/216875/whataretheapplicationsofthepreprocessoroperatorandgotchastoconside
4/6
12/3/2016
cWhataretheapplicationsofthe##preprocessoroperatorandgotchastoconsider?StackOverflow
SCREEN_HANDLER(activeCall)
SCREEN_HANDLER(ringingCall)
SCREEN_HANDLER(heldCall)
theaboveinyourheaderfiles,etc.Itisalsousefulformaintenanceifyouevenhappentowantto
changethedefinitionsand/oraddmethodstothe"objects".
answeredOct19'08at20:15
TallJeff
7,225
34
55
SGlibuses##tobasicallyfudgetemplatesinC.Becausethere'snofunctionoverloading,##is
usedtogluethetypenameintothenamesofthegeneratedfunctions.IfIhadalisttypecalled
list_t,thenIwouldgetfunctionsnamedlikesglib_list_t_concat,andsoon.
answeredOct19'08at20:16
Jack
IuseitforahomerolledassertonanonstandardCcompilerforembedded:
#defineASSERT(exp)if(!(exp)){\
print_to_rs232("Assertfailed:"###exp);\
while(1){}//Letthewatchdogkillus
answeredOct19'08at21:10
c0m4
1,788
27
35
2 Itakeityoumeanbynonstandardthatthecompilerdidnotdostringpastingbutdiddotokenpasting
orwouldithaveworkedevenwithout ## ?PJTraillJun10'15at10:44
Iuseitforaddingcustomprefixestovariablesdefinedbymacros.Sosomethinglike:
UNITTEST(test_name)
expandsto:
void__testframework_test_name()
answeredOct19'08at20:02
JohnMillikin
126k
30
174
202
Themainuseiswhenyouhaveanamingconventionandyouwantyourmacrototake
advantageofthatnamingconvention.Perhapsyouhaveseveralfamiliesofmethods:
image_create(),image_activate(),andimage_release()alsofile_create(),file_activate(),
file_release(),andmobile_create(),mobile_activate()andmobile_release().
Youcouldwriteamacroforhandlingobjectlifecycle:
#defineLIFECYCLE(name,func)(structnamex=name##_create();name##_activate(x);
func(x);name##_release())
Ofcourse,asortof"minimalversionofobjects"isnottheonlysortofnamingconventionthis
appliestonearlythevastmajorityofnamingconventionsmakeuseofacommonsubstringto
formthenames.Itcouldmefunctionnames(asabove),orfieldnames,variablenames,ormost
anythingelse.
answeredOct19'08at20:15
mcherm
8,132
33
44
OneimportantuseinWinCE:
http://stackoverflow.com/questions/216875/whataretheapplicationsofthepreprocessoroperatorandgotchastoconside
5/6
12/3/2016
cWhataretheapplicationsofthe##preprocessoroperatorandgotchastoconsider?StackOverflow
#defineBITFMASK(bit_position)(((1U<<(bit_position##_WIDTH))1)<<(bit_position##
_LEFTSHIFT))
Whiledefiningregisterbitdescriptionwedofollowing:
#defineADDR_LEFTSHIFT0
#defineADDR_WIDTH7
AndwhileusingBITFMASK,simplyuse:
BITFMASK(ADDR)
answeredMay20'13at11:42
GNKeshava
2,773
20
37
Itisveryusefulforlogging.Youcando:
#defineLOG(msg)log_msg(__function__,##msg)
Or,ifyourcompilerdoesn'tsupportfunctionandfunc:
#defineLOG(msg)log_msg(__file__,__line__,##msg)
Theabove"functions"logsmessageandshowsexactlywhichfunctionloggeda
message.
MyC++syntaxmightbenotquitecorrect.
editedOct19'08at20:51
answeredOct19'08at20:31
ya23
9,265
33
34
1 Whatwereyoutryingtodowiththat?Itwouldworkjustaswellwithoutthe"##",sincethereisnoneedto
tokenpaste","to"msg".Wereyoutryingtostringifymsg?Also,FILEandLINEmustbeinuppercase,not
lowercase.bk1eOct19'08at20:44
You'rerightindeed.Ineedtofindtheoriginalscripttoseehow##wasused.Shameonme,nocookie
today!ya23Dec12'08at9:59
http://stackoverflow.com/questions/216875/whataretheapplicationsofthepreprocessoroperatorandgotchastoconside
6/6