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.

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208

5 Answers5

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()
sfstewman
  • 5,589
  • 1
  • 19
  • 26
  • Thanks sfstewman! your answer is really good. I added some more uses. – Grijesh Chauhan Mar 10 '13 at 18:50
  • "*One of the most common case of a macro of this form...*" - is this argument still valid nowadays? – SomeWittyUsername Mar 10 '13 at 18:58
  • 1
    @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. – sfstewman Mar 10 '13 at 19:13
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
nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • 1
    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 http://stackoverflow.com/questions/1306611/how-do-i-implement-no-op-macro-or-template-in-c – hmijail Jul 22 '15 at 13:55
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

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
1

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

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

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
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.

Hogan
  • 69,564
  • 10
  • 76
  • 117