5

What is the use/applicability of macro function without definition:

#ifndef __SYSCALL
#define __SYSCALL(a, b)
#endif

One can find this macro in Linux system in header file /usr/include/asm/msr.h

I also notice macro of following kind.

#define _M(x) x

And only reason to defined this kind of macro that I can think to make code uniform. like in #define SOMETHING (1 << 0). Is there any other hidden(better) use of this kind of macros?

An answer with example will be very helpful. Also can someone provide me a text/link to read about this.

3
  • The __SYSCALL macro is only defined on some architectures. Commented Mar 6, 2013 at 19:20
  • What do you mean by make the code more uniform? Commented Mar 6, 2013 at 19:31
  • @Hogan Sorry I couldn't express clearly by Uniform I means like this #define something 1<<0 Commented Mar 6, 2013 at 19:37

5 Answers 5

13

One of the most common case of a macro of this form:

#define _M(x) x

is to provide backwards compatibility for compilers that only supported the original K&R dialect of C, that predated the now-ubiquitous ANSI C dialect. In the original K&R dialect of the language, function arguments were not specified when declaring the function. In 1989, ANSI standardized the language and incorporated a number of improvements, including function prototypes that declared the number of type of arguments.

int f(int x, double y); /* ANSI C. K&R compilers would not accept this */

int f(); /* Function declared in the original K&R dialect */

While compilers that support the original K&R dialect of C are rare (or extinct) these days, a lot of software was written when both kinds of compilers needed to be supported, and macros provided an easy way to support both. There are still a lot of headers laying about that provide this backwards compatibility.

To provide backwards compatibility for K&R compilers, many header files have the following:

#if ANSI_PROTOTYPES
#  define _P(x) x
#else
#  define _P(x) ()
#endif

...

int f _P((int x, double y));

If the ANSI_PROTOTYPES definition has been correctly set (either by the user or by some prior #ifdef logic), then you get the desired behavior:

  • If ANSI_PROTOTYPES is defined, the definition expands to int f(int x, double y).
  • If ANSI_PROTOTYPES is not defined, the definition expands to int f()
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks sfstewman! your answer is really good. I added some more uses.
"One of the most common case of a macro of this form..." - is this argument still valid nowadays?
@icepack there aren't a lot of new headers being written this way, but it's one of the more common uses you see for macros of that form. I can't think of a whole lot of other uses that I've seen for it.
4

This is often used with conditional expressions to disable a macro by causing it to be preprocessed to nothing. For example (simplified):

#ifdef DEBUG
#define ASSERT(x) if(!(x)) { abort(); }
#else
#define ASSERT(x) /* nothing */
#endif

1 Comment

Such an "empty" function-like macro has lots of potential for trouble. Better define it to ((void) 0) or do {} while(0). Fuller discussion in stackoverflow.com/questions/1306611/…
3

Just a follow-up to my question.

I got good answers. but I am also adding some more helpful example where macros without definition are useful, one can find it helpful in future:

(1): Why do I see THROW in a C library?
uses to share header file between C and C++. The macro name is _THROW(x)

#ifdef __cplusplus
    #define __THROW(x) throw(x)
#else
    #define __THROW(x)
#endif  

(2) to eliminate warnings when a function parameter isn't used:
This use is for c++. In C it will cause an error too few arguments But in C++ it works with no error: (codepad linked)

#define UNUSED(x)
int value = 0;
int foo(int UNUSED(value))
{
    return 42;
}
int main(){
   foo(value);
}

(for this I added c++ tag in my question)

Additionally,
(3): The use of #define _M(x) x is as follows, just to makes code line up uniformly:

/* Signed.  */
 # define INT8_C(c)      c
 # define INT16_C(c)     c
 # define INT32_C(c)     c
 # if __WORDSIZE == 64
 #  define INT64_C(c)    c ## L
 # else
 #  define INT64_C(c)    c ## LL
 # endif

the file is: /usr/include/stdint.h

Comments

1

It means that code that uses that macro will conditionally preprocess away to nothing.

As simple examples, consider debug code, logging or assertions.

Comments

1

This is probably a debug macro or an platform macro. For example lets say I have a debugger attached to INT3. I might have this when I'm debugging

 #define debug() INT3()

Then to be safe I'll add this to production code (to make sure I took them all out)

 #define debug()

This looks like something similar

It could be that in some cases on some systems this code needs to make a call -- for example on a certain CPU architecture or OS. But on your system it is just no-oped.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.