What should be done for DD ?
if
#define HEADING_TITLE_PROJECT_NAME "<= Version Maintenance Based On Comp开发者_如何学运维iled DateTime =>"
#define SIZE_OF_HEADER_FOR_DECORATION_PURPOSE sizeof(HEADING_TITLE_PROJECT_NAME)
#define DD ????
#define HEADING "\r\n"DD"\r\n"HEADING_TITLE_PROJECT_NAME"\r\n"DD"\r\n"
I want to get HEADING string literal as follows:
<==================================================>
<= Version Maintenance Based On Compiled DateTime =>
<==================================================>
The = sign or anything I put once will repeat within <== ... ==> to fill the HEADING_TITLE_PROJECT_NAME space.
Can it be done this way or other. I only want to change the HEADING_TITLE_PROJECT_NAME in coding time and nothing else. JUST THOUGHT IF IT CAN BE DONE :)
<==Edit start==> Something like
#define DD\
char * get()\
{\
char arr[100] = '\0';\
for (int i=0; i < SIZE_OF_HEADER_FOR_DECORATION_PURPOSE - 1; i++)\
{\
arr[i] = "=";\
}\
return arr;\
}
<==Edit ends==>
Unfortunately, there's no automatic way to generate DD
in the standard C preprocessor, as long as you want to use it the way you use in the definition of HEADING
macro.
As long as you insist of having that HEADING
defined they way it is currently defined, I can only suggest using a semi-automatic approach :). Define DD
manually, explicitly.
#define HEADING_TITLE_PROJECT_NAME "<= Version Maintenance Based On Compiled DateTime =>"
#define DD "<==================================================>"
And then just add
STATIC_ASSERT(sizeof HEADING_TITLE_PROJECT_NAME == sizeof DD);
right under it (with your favorite implementation of STATIC_ASSERT
). That way any discrepancy in DD
's length will immediately trigger an error and force the developer to update the DD
.
This is impossible because of sizeof is evaluated after the preprocessor, rather than before.
If you knew the length of the string in advance, it would be.
Because the proprocessor doesn't have any looping constructs, you wind up creating them. Boost does it something like this
#define REPEAT_TIMES(macro, n) REPEAT##n(macro)
#define REPEAT1(macro) MACRO
#define REPEAT2(macro) REPEAT1(macro)MACRO
#define REPEAT3(macro) REPEAT2(macro)MACRO
....
You would then simply:
#define FILLER "="
#define DD "<"REPEAT_TIMES(FILLER, 34)">"
Your implementation of DD
isn't a bad idea, though it suffers from some poor syntax and undefined behavior.
const char *DDD(void)
{
static char arr[] = HEADING_TITLE_PROJECT_NAME;
if(arr[2] == ' ')
for(size_t i = 2; i + 3 < sizeof arr; i++)
arr[i] = '=';
return arr;
}
#define DD DDD()
You can't return a pointer to stack data, so you have to use a static
array. We can make sure it's the right size by having it automatically set to the #define
d string, then checking if it's been filled with '='
yet and, if not, fill it. Then we return a const
pointer to it so that no one tries to modify it.
Your macro defines a function, get
, with unspecified arguments, and returning a modifiable char *
to stack data. Unfortunately, this function will be defined everywhere you use the macro, which will result in many multiple definition errors.
You can't use this with raw string concatenation, but it will work for everything else you want.
精彩评论