gcc 4.4.1
I am maintaining someone's code and I have come across something that I don't understand.
#define RES_API(name, func) name##_##func
Can anyone explain?
Many thanks,
The ## is a concatenation operator. Using RES_API(name1, func1) in your code would be replaced with name1_func1. More information here.
The ## operator concatenates two tokens. In your case, name is appended with an underscore, and that is appended with func.
So RES_API(aName, aFunc) results in aName_aFunc.
By itself, it seems rather annoying. I could see a use when mixing C and C++ code, as C libraries tend to prefix their functions, while C++ libraries would place them in a namespace.
Given an alternate definition, such as:
#define RES_API(name, func) name##::##func
You suddenly have a generic way to switch between a C interface, or C++.
I know you've already got your answer, but there is some great info on the C-FAQ which explains allot of the C Preprocessor magic.
Instead of doing OBJ_DoSomething, with this macro you can do RES_API(OBJ, DoSomething). Personally I think its silly.
Related
Here's a formal grammar brain teaser (maybe :P)
I'm fairly certain there is no context where the character sequence => may appear in a valid C program (except obviously within a string). However, I'm unable to prove this to myself. Can you either:
Describe a method that I can use for an arbitrary character sequence to determine whether it is possible in a valid C program (outside a string/comment). Better solutions require less intuition.
Point out a program that does this. I have a weak gut feeling this could be undecidable but it'd be great if I was wrong.
To get your minds working, other combos I've been thinking about:
:- (b ? 1:-1), !? don't think so, ?! (b ?!x:y), <<< don't think so.
If anyone cares: I'm interested because I'm creating a little custom C pre-processor for personal use and was hoping to not have to parse any C for it. In the end I will probably just have my tokens start with $ or maybe a backquote but I still found this question interesting enough to post.
Edit: It was quickly pointed out that header names have almost no restrictions so let me amend that I'm particularly interested in non-pre-processor code, alternatively, we could consider characters within the <> of #include <...> as a string literal.
Re-edit: I guess macros/pre-processor directives beat this question any which way I ask it :P but if anyone can answer the question for pure (read: non-macro'd) C code, I think it's an interesting one.
#include <abc=>
is valid in a C program. The text inside the <...> can be any member of the source character set except a newline and >.
This means that most character sequences, including !? and <<<, could theoretically appear.
In addition to all the other quibbles, there are a variety of cases involving macros.
The arguments to a macro expansion don't need to be syntactically correct, although of course they would need to be syntactically correct in the context of their expansion. But then, they might never be expanded:
#include <errno.h>
#define S_(a) #a
#define _(a,cosmetic,c) [a]=#a" - "S_(c)
const char* err_names[] = {
_(EAGAIN, =>,Resource temporarily unavailable),
_(EINTR, =>,Interrupted system call),
_(ENOENT, =>,No such file or directory),
_(ENOTDIR, =>,Not a directory),
_(EPERM, =>,Operation not permitted),
_(ESRCH, =>,No such process),
};
#undef _
const int nerr = sizeof(err_names)/sizeof(err_names[0]);
Or, they could be used but in stringified form:
#define _(a,b,c) [a]=#a" "S_(b)" "S_(c)
Note: Why #a but S_(c)? Because EAGAIN and friends are macros, not constants, and in this case we don't want them to be expanded before stringification.
/*=>*/
//=>
"=>"
'=>'
I am trying to implement the standard xor swap algorithm as a C macro.
I have two versions of the macro. One that doesn't worry about the types and one that attempts to cast everything to an integer.
Here are the macro's
#define XOR_SWAP(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define LVALUE_CAST(type,value) (*((type)*)&(value))
#define XOR_CAST_SWAP(type,a,b) (LVALUE_CAST((type),(a))=(type)(a)^(type)(b),LVALUE_CAST((type),(b))=(type)(b)^(type)(a),LVALUE_CAST((type),(a))=(type)(a)^(type)(b))
I know it's a pain to read the one with a cast, but your efforts are appreciated.
The error that I'm getting is:
some_file.c(260,3): expected expression before ')' token
Now, I'm looking at it but I still can't figure out where my problem lies.
I've even used the -save-temps option to capture the preprocessor output and the line looks like this:
((*(((intptr_t))*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2),(*(((intptr_t))*)&((Block2)))=(intptr_t)(Block2)^(intptr_t)(Block1),(*(((intptr_t))*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2));
Before anybody mentions it, I've since realized that I should probably make this a function instead of a macro. Or even better, just use that extra variable to do the swap, it isn't hard.
But I want to know why this macro doesn't work. The brackets seem to match exactly as I wanted them to, so why is it complaining?
The LVALUE_CAST is something I took from #Jens Gustedt's answer in this SO question.
Update:
The macro call that produces that preprocessor output looks like this:
XOR_CAST_SWAP(intptr_t, Block1, Block2);
I don't believe you can wrap types in arbitrary levels of parentheses.* So this compiles fine:
((*(intptr_t*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2),(*(intptr_t*)&((Block2)))=(intptr_t)(Block2)^(intptr_t)(Block1),(*(intptr_t*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2));
* Disclaimer: this is purely empirical! I don't intend to peruse the standard to figure out what the details are...
I have some experience in programming in C but I would not dare to call myself proficient.
Recently, I encountered the following macro:
#define CONST(x) (x)
I find it typically used in expressions like for instance:
double x, y;
x = CONST(2.0)*y;
Completely baffled by the point of this macro, I extensively researched the advantages/disadvantages and properties of macros but still I can not figure out what the use of this particular macro would be. Am I missing something?
As presented in the question, you are right that the macro does nothing.
This looks like some artificial structure imposed by whoever wrote that code, maybe to make it abundantly clear where the constants are, and be able to search for them? I could see the advantage in having searchable constants, but this is not the best way to achieve that goal.
It's also possible that this was part of some other macro scheme that either never got implemented or was only partially removed.
Some (old) C compilers do not support the const keyword and this macro is most probably a reminiscence of a more elaborate sequence of macros that handled different compilers. Used like in x = CONST(2.0)*y; though makes no sense.
You can check this section from the Autoconf documentation for more details.
EDIT: Another purpose of this macro might be custom preprocessing (for extracting and/or replacing certain constants for example), like Qt Framework's Meta Object Compiler does.
There is absolutely no benefit of that macro and whoever wrote it must be confused. The code is completely equivalent to x = 2.0*y;.
Well this kind of macro could actually be usefull when there is a need to workaround the macro expansion.
A typical example of such need is the stringification macro. Refer to the following question for an example : C Preprocessor, Stringify the result of a macro
Now in your specific case, I don't see the benefit appart from extreme documention or code parsing purposes.
Another use could be to reserve those values as future function invocations, something like this:
/* #define CONST(x) (x) */
#define CONST(x) some_function(x)
// ...
double x, y;
x = CONST(2.0)*y; // x = some_function(2.0)*y;
Another good thing about this macro would be something like this
result=CONST(number+number)*2;
or something related to comparisons
result=CONST(number>0)*2;
If there is some problem with this macro, it is probably the name. This "CONST" thing isn't related with constants but with some other thing. It would be nice to look for the rest of the code to know why the author called it CONST.
This macro does have the effect of wrapping parenthesis around x during the macro expansion.
I'm guessing someone is trying to allow for something along the lines of
CONST(3+2)*y
which, without the parens, would become
3+2*y
but with the parens becomes
(3+2)*y
I seem to recall that we had the need for something like this in a previous development lifetime.
I am now studying about the implementation of page table of Linux 2.6.38.8. In linux/include/linux/syscall.c, I found that
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
but I don't fully understand what this piece of code is doing. There are some branches for
SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
and their definition, but the code is quite complicated to understand for me. If anyone know about this implementation, teach me please.
Basically SYSCALL_DEFINE is defined by another define which is called SYSCALL_DEFINEx. In addition it used string concatenation to build the second parameter, which is the same name preceded by the "_" character. In addition it uses VA_ARGS (this is a c99 feature) which passes all the specified parameters to the SYSCALL_DEFINEx macro.
In preprocessors, we can have switch between macros like,
#define BUFF(n) BUFF_##n
So, BUFF(1) would get replaced by BUFF_1, BUFF(2) would get replaced by BUFF_2 and song
Can this be applicable to C variables? i.e., choosing between similar variables dynamically. I understand it is a weird situation and can be handled using arrays or any other constructs.. but the situation demands me such situation.. could u plz help with this.. thanks in advance
Yes, you can use that macro to apply BUFF_ to just anything. The preprocessor will expand macros and then the compiler will try to compile the result. The latter might fail, since if you use BUFF(+) you get BUFF_+ and that's not a valid variable name.
Sure, you can do this. preprocessor macros are just text replacements that are done to the code before compilation. You can't do this during runtime, though.