Can a macro remove characters from its arguments? - c

Is it possible to define a macro that will trim off a portion of the string argument passed in?
For example:
//can this be defined?
#define MACRO(o) ???
int main(){
printf(MACRO(ObjectT)); //prints "Object" not "ObjectT"
}
Would it be possible for a macro that trim off the last character 'T'?

You can do it for specific strings that you know in advance, presented to the macro as symbols rather than as string literals, but not for general symbols and not for string literals at all. For example:
#include <stdio.h>
#define STRINGIFY(s) # s
#define EXPAND_TO_STRING(x) STRINGIFY(x)
#define TRUNCATE_ObjectT Object
#define TRUNCATE_MrT Pity da fool
#define TRUNCATE(s) EXPAND_TO_STRING(TRUNCATE_ ## s)
int main(){
printf(TRUNCATE(ObjectT)); // prints "Object"
printf(TRUNCATE(MrT)); // prints "Pity da fool"
}
That relies on the token-pasting operator, ##, to construct the name of a macro that expands to the truncated text (or, really, the replacement text), and the stringification operator, #, to convert the expanded result to a string literal. There's a little bit of required macro indirection in there, too, to ensure that all the needed expansions are performed.

Well, at least it should print "Object"...
//can this be defined?
#define MACRO(o) #o "\b \b"
int main(){
printf(MACRO(ObjectT)); //prints "Object" not "ObjectT"
}
And no, you can't strip character using preprocessor only without actual C code (say, malloc+strncpy) to do that.

With the preprocessor? No. It sounds like what you really want to do is something like this:
Code not tested
#define STRINGIFY(o) #o
char* serialize(char* s)
{
if (strcmp(s, "ObjectT") == 0) return "Object";
}
int main(){
printf(serialize(STRINGIFY(#o))); //prints "Object" not "ObjectT"
}

Related

C macro stringifying a variable

When can I pass variable's value to a macro for stringifying?
For example the code taken from this post works with a constant-defined macro.
#define MAX_STRING_LENGTH 20
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
{
...
char word[MAX_STRING_LENGTH+1];
scanf("%" STRINGIFY(MAX_STRING_LENGTH) "s", word);
...
}
However I cannot use it with a variable such as:
{
...
int val = 20;
char word[MAX_STRING_LENGTH+1];
scanf("%" STRINGIFY(val) "s", word);
...
}
since the compilation is successful with this warning:
warning: invalid conversion specifier 'v' [-Wformat-invalid-specifier]
scanf("%" STRINGIFY(var) "s", word);
~~~^~~~~~~~~~~~~
test2.c:4:22: note: expanded from macro 'STRINGIFY'
#define STRINGIFY(x) STRINGIFY2(x)
^
test2.c:5:23: note: expanded from macro 'STRINGIFY2'
#define STRINGIFY2(x) #x
^
<scratch space>:466:2: note: expanded from here
"var"
^
1 warning generated
but the run of the code does not wait for any input.
On the contrary in this other post it was possible to pass a variable to this macro:
#define PRINT(int) printf(#int "%d\n",int)
...
int var =8;
PRINT(var);
What is the difference between the two cases? How can I modify the first one so that it accepts also variables?
I tried using %d inside the macro but I was not successful.
The preprocessor always operates on tokens only.
A macro is not a function. You don't pass it a variable (by value). You pass a token sequence. In STRINGIFY(MAX_STRING_LENGTH) the token sequence is MAX_STRING_LENGTH, and in STRINGIFY(val) it's the token sequence val.
MAX_STRING_LENGTH is itself a macro, and due to how STRINGIFY is defined to work, the macro will be expanded by the preprocessor before turning it a string literal. So 20 is in turn the token which gets # applied to it, and it produces "20" as a string literal.
On the other hand val is not a macro, the preprcosseor is not going to expand it. It's going to keep the token sequence as val. The fact val is the name of a variable with some value means nothing to the preprocessor, it only cares about tokens. So val is transformed into the literal "val".
The example you brought from another post worked because it expanded to this:
printf("var" "%d\n", var);
The variable name in #int turns into a literal, there is no magic that lets the preprocessor read a variable's value. The fact var 8 is printed is only because var is passed as an argument to printf! It's printed at run-time by the %d specifier.
Finally, when experimenting with the preprcoessor it's always helpful to look at the source file after prpeprocessing is done, but before the file is compiled. The gcc -E flag (or equivalent for your compiler) can help you do that.
STRINGIFY(val) will result in "val", not the value you wanted to stringify, so you get a final format string of "%vals" ("%" "val" "s"). That's how the C preprocessor works, it does just text replacements, nothing more.
The PRINT example:
#define PRINT(int) printf(#int "%d\n", int)
PRINT(var); // to be resolved
printf(#var "%d\n", var); // intermediate result
printf("var" "%d\n", var); // final result, this is what the C compiler sees
But why did it work with MAX_STRING_LENGTH?
#define MAX_STRING_LENGTH 20
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
STRINGIFY(MAX_STRING_LENGTH) // to be resolved
STRINGIFY2(20) // intermediate step; STRINGIFY2 known as macro, thus:
#20 // another intermediate step
"20" // final result

Printing define name c

#define Page 5
void printSystemInfo() {
printf ("%i", Page);
}
Thats my code can anyone explain me how to print Page 5 in the console?
For now my console looks like this "5" But I want to have "Page 5"
Thanks for helping !
You can use a little preprocessor trick. We have the # operator, which will convert a symbol into a string.
#define _(a) #a
When you call _(foo), it translates it as "foo". So, in your case, you could do something like:
#include <stdio.h>
#define _(a) # a
#define PAGE 5
int main(int argc, char *argv[])
{
printf("%s: %i\n", _(PAGE), PAGE);
return 0;
}
What this will do is:
We define a macro named _ that takes one parameter a. This macro uses the operator # from the preprocessor (called stringification). This will case a named passed to the macro to be converted into a string. Example: _(foo) gets translated to "foo".
In main, the printf() call is then translated as printf("%s: %i\n", "PAGE", 5);. In a stepwise way, when the preprocessor sees the _(PAGE) symbol, it translates it as "PAGE".
The inner workings of this things is explained in the above link, which I quote (my markings):
Sometimes you may want to convert a macro argument into a string constant. Parameters are not replaced inside string constants, but you can use the ‘#’ preprocessing operator instead. When a macro parameter is used with a leading ‘#’, the preprocessor replaces it with the literal text of the actual argument, converted to a string constant. Unlike normal parameter replacement, the argument is not macro-expanded first. This is called stringification.
Here you go. This is very trivial stuff, but please ask if something is unclear.
#define Page 5
void printSystemInfo()
{
printf((char const[])??<0120,0141,0147,0145,0040,0045,0151,!"bad"??>,Page);
}

Macro name escaping without undef

I want to know if there is any way to escape macro name and actually show the real name :
#define BUFF_SIZE 500
printf("%d", BUFF_SIZE);
Is it possible to not expand BUFF_SIZE here without removing the define?
Stringification:
Sometimes you may want to convert a macro argument into a string
constant. Parameters are not replaced inside string constants, but you
can use the ‘#’ preprocessing operator instead. When a macro parameter
is used with a leading ‘#’, the preprocessor replaces it with the
literal text of the actual argument, converted to a string constant.
Unlike normal parameter replacement, the argument is not
macro-expanded first. This is called stringification.
#include <stdio.h>
#define BUFF_SIZE 500
#define STR(x) #x
int main(void)
{
printf("%s\n", STR(BUFF_SIZE));
return 0;
}
Note that you can't print a string with %d, use %s.

Different behavior in visual c++ versus gcc/clang while stringifying parameter which contains comma

I'm using stringizing operator to convert parameter which may contains comma passed to a macro into string. As I know, some characters cannot be stringified – notably, the comma(,) because it is used to delimit parameters and the right parenthesis()) because it marks the end of the parameter. So I use a variadic macro to pass commas to the stringizing operator like this:
#include <stdio.h>
#define TEST 10, 20
#define MAKE_STRING(...) #__VA_ARGS__
#define STRING(x) MAKE_STRING(x)
int main()
{
printf("%s\n", STRING(TEST) );
return 0;
}
it works fine. But it occurs to me what would happen without variadic macro, so I modify the macro: #define MAKE_STRING(x) #x. It compiles fine unexpectedly in visual c++ 2008/2010, and output 10, 20 while gcc/clang give the compilation error as expected:
macro "MAKE_STRING" passed 2 arguments, but takes just 1
So my question: is the Visual c++ doing additional work or the behavior is undefined?
VS in general allows extra parameters in macros and then just drops them silently:
STRING(10, 20, 30) - still works and prints 10. This is not the case here, but it pretty much means VS don't even have the error gcc threw at you.
It's not any additional work but "merely" a difference in substitution order.
I am not sure if this will answer your question but i hope this will help you solving your problem. When defining a string constant in C, you should include it in double quotes (for spaces). Also, the # macro wrap the variable name inside double quotes so, for example, #a become "a".
#include <stdio.h>
#define TEST "hello, world"
#define MAKE_STRING(x) #x
int main()
{
int a;
printf("%s\n", TEST);
printf("%s\n", MAKE_STRING(a));
return 0;
}
I compiled this code using gcc 4.7.1 and the output is:
hello, world
a
I dunno why this has upvotes, or an answer got downvoted (so the poster deleted it) but I don't know what you expect!
#__VA_ARGS__ makes no sense, suppose I have MACRO(a,b,c) do you want "a,b,c" as the string?
http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros
Read, that became standard behaviour, variable length arguments in macros allow what they do in variable length arguments to functions. The pre-processor operates on text!
The only special case involving # is ##, which deletes a comma before the ## if there are no extra arguments (thus preventing a syntax error)
NOTE:
It is really important you read the MACRO(a,b,c) part and what do you expect, a string "a,b,c"? or "a, b, c" if you want the string "a, b, c" WRITE THE STRING "a, b, c"
Using the # operator is great for stuff like
#define REGISTER_THING(THING) core_of_program.register_thing(THING); printf("%s registered\n",#THING);

Determine #defined string length at compile time

I have a C-program (an Apache module, i.e. the program runs often), which is going to write() a 0-terminated string over a socket, so I need to know its length.
The string is #defined as:
#define POLICY "<?xml version=\"1.0\"?>\n" \
"<!DOCTYPE cross-domain-policy SYSTEM\n" \
"\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" \
"<cross-domain-policy>\n" \
"<allow-access-from domain=\"*\" to-ports=\"8080\"/>\n" \
"</cross-domain-policy>\0"
Is there please a way, better than using strlen(POLICY)+1 at the runtime (and thus calculating the length again and again)?
A preprocessor directive, which would allow setting POLICY_LENGTH already at compile time?
Use sizeof(). e.g. sizeof("blah") will evaluate to 5 at compile-time (5, not 4, because the string literal always includes an implicit null-termination character).
Use 1+strlen(POLICY) and turn on compiler optimizations. GCC will replace strlen(S) with the length of S at compile time if the value from S is known at compile time.
I have a similar problem when using an outdated compiler (VisualDSP) on an embedded platform which does not yet support C++11 (and so I can't use constexpr).
I don't need to evaluate the string length in the precompiler, but I do need to optimize it into a single assignment.
Just in case someone needs this in the future, here's my extremely hacky solution which should work on even crappy compilers as long as they do proper optimization:
#define STRLENS(a,i) !a[i] ? i : // repetitive stuff
#define STRLENPADDED(a) (STRLENS(a,0) STRLENS(a,1) STRLENS(a,2) STRLENS(a,3) STRLENS(a,4) STRLENS(a,5) STRLENS(a,6) STRLENS(a,7) STRLENS(a,8) STRLENS(a,9) -1)
#define STRLEN(a) STRLENPADDED((a "\0\0\0\0\0\0\0\0\0")) // padding required to prevent 'index out of range' issues.
This STRLEN macro will give you the length of the string literal that you provide it, as long as it's less than 10 characters long. In my case this is enough, but in the OPs case the macro may need to be extended (a lot). Since it is highly repetitive you could easily write a script to create a macro that accepts 1000 characters.
PS: This is just a simple offshoot of the problem I was really trying to fix, which is a statically-computed HASH value for a string so I don't need to use any strings in my embedded system. In case anyone is interested (it would have saved me a day of searching and solving), this will do a FNV hash on a small string literal that can be optimized away into a single assignment:
#ifdef _MSC_BUILD
#define HASH_FNV_OFFSET_BASIS 0x811c9dc5ULL
#define HASH_TYPE int
#else // properly define for your own compiler to get rid of overflow warnings
#define HASH_FNV_OFFSET_BASIS 0x811c9dc5UL
#define HASH_TYPE int
#endif
#define HASH_FNV_PRIME 16777619
#define HASH0(a) (a[0] ? ((HASH_TYPE)(HASH_FNV_OFFSET_BASIS * HASH_FNV_PRIME)^(HASH_TYPE)a[0]) : HASH_FNV_OFFSET_BASIS)
#define HASH2(a,i,b) ((b * (a[i] ? HASH_FNV_PRIME : 1))^(HASH_TYPE)(a[i] ? a[i] : 0))
#define HASHPADDED(a) HASH2(a,9,HASH2(a,8,HASH2(a,7,HASH2(a,6,HASH2(a,5,HASH2(a,4,HASH2(a,3,HASH2(a,2,HASH2(a,1,HASH0(a))))))))))
#define HASH(a) HASHPADDED((a "\0\0\0\0\0\0\0\0\0"))
sizeof works at compile time
#define POLICY "<?xml version=\"1.0\"?>\n" \
"<!DOCTYPE cross-domain-policy SYSTEM\n" \
"\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" \
"<cross-domain-policy>\n" \
"<allow-access-from domain=\"*\" to-ports=\"8080\"/>\n" \
"</cross-domain-policy>\0"
char pol[sizeof POLICY];
strcpy(pol, POLICY); /* safe, with an extra char to boot */
If you need a pre-processor symbol with the size, just count the characters and write the symbol yourself :-)
#define POLICY_LENGTH 78 /* just made that number up! */
Per other answers, sizeof(STRING) gives the length (including the \0 terminator) for string literals. However, it has one downside: if you accidentally pass it a char* pointer expression instead of a string literal, it will return an incorrect value–the pointer size, which will be 4 for 32-bit programs and 8 for 64-bit–as the following program demonstrates:
#include <stdio.h>
#define foo "foo: we will give the right answer for this string"
char bar[] = "bar: and give the right answer for this string too";
char *baz = "baz: but for this string our answer is quite wrong";
#define PRINT_LENGTH(s) printf("LENGTH(%s)=%zu\n", (s), sizeof(s))
int main(int argc, char **argv) {
PRINT_LENGTH(foo);
PRINT_LENGTH(bar);
PRINT_LENGTH(baz);
return 0;
}
However, if you are using C11 or later, you can use _Generic to write a macro which will refuse to compile if passed something other than a char[] array:
#include <stdio.h>
#define SIZEOF_CHAR_ARRAY(s) (_Generic(&(s), char(*)[sizeof(s)]: sizeof(s)))
#define foo "foo: we will give the right answer for this string"
char bar[] = "bar: and give the right answer for this string too";
char *baz = "baz: but for this string our answer is quite wrong";
#define PRINT_LENGTH(s) printf("LENGTH(%s)=%zu\n", (s), SIZEOF_CHAR_ARRAY(s))
int main(int argc, char **argv) {
PRINT_LENGTH(foo);
PRINT_LENGTH(bar);
// Will fail to compile if you uncomment incorrect next line:
// PRINT_LENGTH(baz);
return 0;
}
Note this doesn't only work for string literals – it also works correctly for mutable arrays, provided they are actual char[] arrays of fixed length as a string literal is.
As written, the above SIZEOF_CHAR_ARRAY macro will fail for const expressions (although you'd think string literals ought to be const, for backward compatibility reasons they are not):
const char quux[] = "quux is const";
// Next line will fail to compile:
PRINT_LENGTH(quux);
However, we can improve our SIZEOF_CHAR_ARRAY macro so the above example will also work:
#define SIZEOF_CHAR_ARRAY(s) (_Generic(&(s), \
char(*)[sizeof(s)]: sizeof(s), \
const char(*)[sizeof(s)]: sizeof(s) \
))

Resources