Vous êtes sur la page 1sur 6

12/3/2016

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

Onethingtobeawareofwhenyou'reusingthetokenpaste(' ## ')orstringizing(' # ')


preprocessingoperatorsisthatyouhavetouseanextralevelofindirectionforthemtowork
properlyinallcases.
Ifyoudon'tdothisandtheitemspassedtothetokenpastingoperatoraremacrosthemselves,
you'llgetresultsthatareprobablynotwhatyouwant:
#include<stdio.h>
#defineSTRINGIFY2(x)#x
#defineSTRINGIFY(x)STRINGIFY2(x)
#definePASTE2(a,b)a##b
#definePASTE(a,b)PASTE2(a,b)
#defineBAD_PASTE(x,y)x##y
#defineBAD_STRINGIFY(x)#x
#defineSOME_MACROfunction_name
intmain()
{
printf("buggyresults:\n");
printf("%s\n",STRINGIFY(BAD_PASTE(SOME_MACRO,__LINE__)));
printf("%s\n",BAD_STRINGIFY(BAD_PASTE(SOME_MACRO,__LINE__)));
printf("%s\n",BAD_STRINGIFY(PASTE(SOME_MACRO,__LINE__)));
printf("\n""desiredresult:\n");
printf("%s\n",STRINGIFY(PASTE(SOME_MACRO,__LINE__)));
}

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

Vous aimerez peut-être aussi