I have a (possibly faulty) school assignment regarding the C-preprocessor, in which I should essentially define a macro which allows
Today is the 9.
to compile to
int a = 9;
Note the "." after the 9. The rest of the program is similar, I have no problem with that.
Now I replaced "Today" by int (#define Today int), "is" by a, "the" by = but I don't know what to do with the ".", given if I just blindly replace it by doing
#define . ;
I get a compile-time error.
Is it even possible to do something with the dot?
Is it possible to redefine "." using macros in C?
No.
given if I just blindly replace it by doing
#define . ;
I get a compile-time error. Is it even possible to do something with
the dot?
No, it is not possible.
In the first place, the . in the text presented is not a separate token according to C's rules. It is part of 9., a floating-point constant. Macro replacement operates only on complete tokens.
In the second place, macro replacement is not a general search / replace. Macro names must be C identifiers, which start with either an underscore or a Latin letter, and contain only underscores, Latin letters, and decimal digits. Thus, it is not possible to define either . by itself or the full 9. as a macro name.
#define Today int
#define is a
#define the = (int)
void foo(void)
{
Today is the 9.;
printf("%d\n", is);
}
Related
So when looking into getting my define macro to work, I found the # and ## macro helpers, and used them to simplify my macro. The key part of the macro sets a variable to a string containing the name of the variable (but not the variable name alone). As a simplified example, let's take a macro called SET(X) that should expand SET(something) into something = "pre_something".
The only way I've found to do it so far is with two macros like #define QUOTE(X) #X and #define SET(X) X = QUOTE(pre_##X). However, using multiple macros seems excessive, and may cause problems with further macro expansion (I think). Is there a cleaner, one-line way of doing the same thing?
#define SET(x) x = "pre_"#x
C does string concatenation at compile time, so two string literals next to each other are concatenated.
"hello " "world" -> "hello world"
I'm working in a C program and I came across a problem. I have this
#define NUMBER_OF_OPTIONS 5
#define NAME_OPTION1 "Partida Rapida"
#define NAME_OPTION2 "Elige Nivel"
#define NAME_OPTION3 "Ranking"
#define NAME_OPTION4 "Creditos"
#define NAME_OPTION5 "Exit"
for (iterator = 1; iterator <= NUMBER_OF_OPTIONS; iterator++){
menu_options[iterator-1]= NAME_OPTION + iterator
}
I want that "NAME_OPTION + iterator" takes the value of the corresponding #define. For example if the variable "iterator" is equal to one, I want menu_options[iterator-1] to take the value of NAME_OPTION1, which is "Partida Rapida".
How can I get this?
Essentially, you can't. #define macros are handled by the C Preprocessor and do textual substitution wherever that macro appears in the code. The macro NAME_OPTION has not been defined, so the compiler should complain. C does not allow appending numbers onto strings, or especially onto symbols like NAME_OPTION. Use an array of const char*, which you can then refer to with your iterator.
You can't use defines as this, you can do:
const char *menu_options[5] = {
"Partida Rapida",
"Elige Nivel",
"Ranking",
"Creditos",
"Exit"
};
If you use #define macro, you just tell preprocessor to replace every occurence of defined word by something else before the code is compiled into machine code.
In this case NUMBER_OF_OPTIONS will be replaced by 5, but there's no occurence of NAME_OPTION*, so nothing will be replaced and you'll probably get an error while preprocessing.
Piere's solutions shows how to do it, but I highly doubt that there's an iterator over char *array, so you have to iterate over given array using an integer index.
I have found two different things in two well known books in c,
first one is
"Formal parameters are not replaced in quoted string in macro expansion" - by K&R c language page 76
second one is a code,
#define PRINT(var,format) printf("variable is %format\n",var)
PRINT(x_var,f);
later macro invocation would be expanded as
printf("x_var is %f\n",x_var);
this is by programming in ansi c - E. balagurusamy at page 448.
Surely two citations are contradictory one with another. as far I know first one is true and my compiler giving me result so. But second book is also well known and popular. I want to know if there was such things in previous versions of c or the second citation is a false one.
The second book is wrong: it is easy to check that the macro will not be expanded like that. However, you can get the effect that they describe by stringizing tokens using the # preprocessor operator:
#define PRINT(var,format) printf(#var" is %"#format"\n",var)
Now you can print your variable as follows:
int xyz = 123;
PRINT(xyz, d);
Here is a link to a working sample on ideone.
Note the addition of the double quotes before and after the '#format', and the '#' before 'var' and 'format'. The '#' operator causes the value of the variable to be made into a quoted string -- with double quotes of its own. This makes the replaced strings be four quoted strings in a row, that the C compiler recognizes as a request to concatenate into one string. Thus the strings: "xyz", " is %", "d" and "\n" are concatenated into: "xyz is %d\n"
(Note this example is different from the example in the original question in that the orignal example had "variable is..." where the answer replaced 'variable' with an instance of the 'var' macro argument)
The book is correct. For it's time. I wrote a little test program to verify it (you don't appreciate text editors until you have programmed in ed):
#define PRINT(fmt,val) printf("val = %fmt\n", (val))
main()
{
int x;
x = 5;
PRINT(d, x);
}
I compiled it on a PDP-11 running Unix V6. Running the program produces this output:
x = 5
This is even pre K&R C. The "feature" was removed in one of the later iterations of C, and made official in ISO C90.
I'm taking a look at an application that defines a large set of constant arrays. What really confuses me is the use of two pound signs next to each other in a macro. For example:
#define r0(p,q,r,s) 0x##p##q##r##s
What do those two pound signs mean?
## provides a way to concatenate actual arguments during macro expansion.
## concattenates symbols. So for example if the value of p is ab, 0x##p would become 0xab.
Als and sepp2k give correct answer.
However I would like to add, that this macro seems to be completely unnecessary.
unsigned int value = r0(b,e,a,f);
can be replaced by better and shorter:
unsigned int value = 0xbeaf;
When using C preprocessor one can stringify macro argument like this:
#define TO_STRING(x) "a string with " #x
and so when used, the result is as follows:
TO_STRING(test) will expand to: "a string with test"
Is there any way to do the opposite? Get a string literal as an input argument and produce a C identifier? For example:
TO_IDENTIFIER("some_identifier") would expand to: some_identifier
Thank you for your answers.
EDIT: For those wondering what do I need it for:
I wanted to refer to nodes in a scene graph of my 3D engine by string identifiers but at the same time avoid comparing strings in tight loops. So I figured I'll write a simple tool that will run in pre-build step of compilation and search for predefined string - for example ID("something"). Then for every such token it would calculate CRC32 of the string between the parenthesis and generate a header file with #defines containing those numerical identifiers. For example for the string "something" it would be:
#define __CRC32ID_something 0x09DA31FB
Then, generated header file would be included by each cpp file using ID(x) macros. The ID("something") would of course expand to __CRC32ID_something, so in effect what the compiler would see are simple integer identifiers instead of human friendly strings. Of course now I'll simply settle for ID(something) but I thought that using quotes would make more sense - a programmer who doesn't know how the ID macro works can think that something without quotes is a C identifier when in reality such identifier doesn't exist at all.
No, you can't unstringify something.
//unstringify test
enum fruits{apple,pear};
#define IF_WS_COMPARE_SET_ENUM(x) if(ws.compare(L#x)==0)f_ret=x;
fruits enum_from_string(wstring ws)
{
fruits f_ret;
IF_WS_COMPARE_SET_ENUM(apple)
IF_WS_COMPARE_SET_ENUM(pear)
return f_ret;
}
void main()
{
fruits f;
f=enum_from_string(L"apple");
f=enum_from_string(L"pear");
}
You can create an identifier from a string, this operation is called token-pasting in C :
#define paste(n) x##n
int main(){
int paste(n) = 5;
printf("%d" , x5);
}
output : 5