Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is meaning of this ## in this macro from kernel code [closed]

i found this macro in one kernel code.. http://lxr.free-electrons.com/source/arch/alpha/include/asm/io.h?v=3.0;a=arm#L140

#define IO_CONCAT(a,b)  _IO_CONCAT(a,b)
#define _IO_CONCAT(a,b) a ## _ ## b

i am unable to understand the meaning of this.Does anybody know this?

Edit :

Then here what it will return

  return IO_CONCAT(__IO_PREFIX,readl)(addr);
like image 949
Jeegar Patel Avatar asked Dec 01 '22 23:12

Jeegar Patel


2 Answers

Double hash is used to concatenate two tokens together:

#define CONCAT(a,b) a ## b

CONCAT(x, y) # Gives 'xy'

However, such naive implementation doesn't work in case when one of the arguments being passed is a macro itself:

#define Z y
CONCAT(x, Z) # Gives 'xZ', not 'xy' as one might expect

That is why macro indirection is used in your question:

#define CONCAT(a,b)  __CONCAT(a,b)
#define __CONCAT(a,b) a ## b

#define Z y
CONCAT(x, Z) # Gives 'xy' 

UPD.

Now consider the concrete example you're asking about:

return IO_CONCAT(__IO_PREFIX,readl)(addr);

Here __IO_PREFIX is obviously a macro (uppercase identifiers in Linux kernel are often macros). It is defined in several places, one of them is:

#define __IO_PREFIX             generic

Now let's see which steps are taken to expand the original statement:

  1. Expand __IO_PREFIX:
    return IO_CONCAT(generic,readl)(addr);
    
  2. Expand IO_CONCAT(...):
    return _IO_CONCAT(generic,readl)(addr);
    
  3. Expand _IO_CONCAT(...):
    return generic_readl(addr);
    
like image 149
Eldar Abusalimov Avatar answered Dec 03 '22 12:12

Eldar Abusalimov


That's token pasting. It concatenates the tokens together. So IO_CONCAT(foo,bar) would expand to foo_bar.

It is defined in C99 in §6.10.3.3:

If, in the replacement list of a function-like macro, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument’s preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.)

For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token. Placemarker preprocessing tokens are handled specially: concatenation of two placemarkers results in a single placemarker preprocessing token, and concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token. If the result is not a valid preprocessing token, the behavior is undefined. The resulting token is available for further macro replacement. The order of evaluation of ## operators is unspecified.

like image 42
Mat Avatar answered Dec 03 '22 14:12

Mat