hi guys. i was going through a code where i saw an enum written as:

typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;

# define inside enum. wat does it mean. Also i saw:

#if !MEM_USE_POOLS
static
#endif
const u16_t memp_sizes[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_ALIGN_SIZE(size),
#include "lwip/memp_std.h"
};

I am not able to understand that what will be the elements of the array.

Please help

I have seen and used this trick before. The file memp_std will contain a list of items defining the memory pools for the system something like this

LWIP_MEMPOOL(Pool1,100,8,"8 byte pool") 
LWIP_MEMPOOL(Pool2,100,16,"16 byte pool") 
LWIP_MEMPOOL(Pool3,100,32,"32 byte pool") 
LWIP_MEMPOOL(Pool4,100,64,"64 byte pool") 
...

normally without inclusion tags.

Then when you want to do something with memory pools, like define an enaum for each one you #define the symbol LWIP_MEMPOOL to produce the desired output, a valid enum tag in this case, and include the file. Personally I would then undefine LWIP_MEMPOOL.

The second example you posted then #defines LWIP_MEMPOOL to produce the initialiser for an array containing the block size for each pool.

ya wat u are saying is right that the other file ( memp_std ) is some what like this. But i am not able to understand your reply properly.

Lets say if i have the file ( memp_std.h ) as you said:


LWIP_MEMPOOL(Pool1,100,8,"8 byte pool")

LWIP_MEMPOOL(Pool2,100,16,"16 byte pool")

LWIP_MEMPOOL(Pool3,100,32,"32 byte pool")

LWIP_MEMPOOL(Pool4,100,64,"64 byte pool")

and now if i have an enum as

typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;

then what exactly is the use of #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name in the enum. please elaborate a bit.

This seems like an interesting question so I will ad myself to this discussion

@Banfa can you explain this concept with a bit of more detail ?

OK lets get this straight, I personally would write this

typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;

as

#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
typedef enum {
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;
#undef LWIP_MEMPOOL

I put the #define outside the enum because I don't think it looks good inside and I #undef the symbol once I have finished using it in case I need to use it again later.

The exact use, in this case of the #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, in combination with the file memp_std.h is to provide a definition of LWIP_MEMPOOL that results in a valid line in the enum, the result being an enum value for every pool in the memory manager.

The line LWIP_MEMPOOL(Pool1,100,8,"8 byte pool") under the definition of the the symbol LWIP_MEMPOOL as #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, processed by the preprocessor results in the compiler seeing the code line MEMP_Pool1,

so the actual code listing

typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;

After preprocessing using the version of memp_std.h that I gave results in the compiler seeing

typedef enum {
MEMP_Pool1,
MEMP_Pool2,
MEMP_Pool3,
MEMP_Pool4,
MEMP_MAX
} memp_t;

ie it defines an enum entry for every pool.

The concept is simple, you have a group of objects whose values are never going to change an runtime and you want to automatically produce the data and symbols to handle them, but there are several different data objects and symbols being defined and you want to make sure you don't ever accidentally miss one out.

What you do is build a table of data describing the objects, that is the contents of memp_std.h and you use the preprocessor to process that table into compilable C (or C++) code using the bits of information that are relevant for what you are doing.

So in the example above producing an enum ignores the number and size of the memory blocks and the pool description using only the pool name. The other example in the OP creates an array of sizes for each memory pool which only uses the size. Depending on the platform you may have a structure that actually allocates the data for the memory pools statically using both number and size.

It allows you to define all the relevant information once in a single place and then let the preprocessor (and compiler) produce the code you need to make it all work.

For those familiar with C++ it is a (very) crude way to implement templates in C.

Edited 3 Years Ago by Reverend Jim: Fixed formatting

Thanx a Lot.....

It really helped me to understand the code in a better way.

One more thing i wanted to ask. U have used the comma operator after this line

#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,

I tried to look for the functioning of the comma operator but could not find anything relevent to this.

Ca u plzzzz tell me the use of comma operator here. I mean we never use comma operator at the end of #define..

OK lets get this straight, I personally would write this
typedef enum {
Thanx a lot.. It really helped me to undersatnd the code.

#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;

as

#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
typedef enum {
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;
#undef LWIP_MEMPOOL

I put the #define outside the enum because I don't think it looks good inside and I #undef the symbol once I have finished using it in case I need to use it again later.

The exact use, in this case of the #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,, in combination with the file memp_std.h is to provide a definition of LWIP_MEMPOOL that results in a valid line in the enum, the result being an enum value for every pool in the memory manager.

The line LWIP_MEMPOOL(Pool1,100,8,"8 byte pool") under the definition of the the symbol LWIP_MEMPOOL as #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, processed by the preprocessor results in the compiler seeing the code line MEMP_Pool1,

so the actual code listing

typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;

After preprocessing using the version of memp_std.h that I gave results in the compiler seeing

typedef enum {
MEMP_Pool1,
MEMP_Pool2,
MEMP_Pool3,
MEMP_Pool4,
MEMP_MAX
} memp_t;

ie it defines an enum entry for every pool.

The concept is simple, you have a group of objects whose values are never going to change an runtime and you want to automatically produce the data and symbols to handle them, but there are several different data objects and symbols being defined and you want to make sure you don't ever accidentally miss one out.

What you do is build a table of data describing the objects, that is the contents of memp_std.h and you use the preprocessor to process that table into compilable C (or C++) code using the bits of information that are relevant for what you are doing.

So in the example above producing an enum ignores the number and size of the memory blocks and the pool description using only the pool name. The other example in the OP creates an array of sizes for each memory pool which only uses the size. Depending on the platform you may have a structure that actually allocates the data for the memory pools statically using both number and size.

It allows you to define all the relevant information once in a single place and then let the preprocessor (and compiler) produce the code you need to make it all work.

For those familiar with C++ it is a (very) crude way to implement templates in C.

Edited 3 Years Ago by mike_2000_17: Fixed formatting

That is not the comma operator. That is the comma syntax element required in-between enum values when defining an enum. Like I said the combination of the #define and the contents of memp_std.h has to result in valid syntax for defining an enum.

Lets say i have an enum as:

enum colours
{
RED,
BLUE,
GREEN
};

Here as we do i put comma to separete the different elements of enum.

NOW I WRITE A TEST PROGRAM AS:

#include<stdio.h>

int main()
{ 
    enum colours
    {
    #include "./c.h"
    PINK 
    };
    enum colours ABC;
    ABC = GREEN;
    printf(" The Colour numbers are %d ",ABC);
    return 0;
}

c.h file is:

#define RED     10
#define GREEN   20
#define BLUE    30

So from my understanding, including the file c.h ( i have not put any commas at the end of the file) makes the enum as:

enum colours
{
RED =   10,
GREEN= 20,
BLUE=30,
PINK 
};

But in the example of memory pools

#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
typedef enum {
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;
#undef LWIP_MEMPOOL

From what i understood, the contents of the file lwip/memp _std.h (LWIP_MEMPOOL(Pool1,100,8,"8 byte pool") as MEMP_Pool1 and so on ) will behave as the elements of enum as in the above example. So why putting a comma at the end of #define?.

Lets say the rewrite the whole thing as:

 #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name // no comma here since we normally dnt use with define
 typedef enum {

 #include "lwip/memp_std.h", // putting a comma here since the file contents( POOL1, POOL2...) will be the elements of enum

MEMP_MAX

 } memp_t;

 #undef LWIP_MEMPOOL

What is wrong with what i have written.?

That is not the comma operator. That is the comma syntax element required in-between enum values when defining an enum. Like I said the combination of the #define and the contents of memp_std.h has to result in valid syntax for defining an enum.

Edited 3 Years Ago by mike_2000_17: Fixed formatting

No your example with colour is all wrong, you just define a few symbols you never create enum entries for RED, GREEn and BLUE. That is the code you have written is not equivalent and does not pre-process to

enum colours
{
RED = 10,
GREEN= 20,
BLUE=30,
PINK
};

In particular the contents of c.h is nothing like the contents of memp_std.h, memp_std.h does not #define anything.


When you define an enum normally you have a , between each element. This is a syntactical requirement. The comma at the end of #define LWIP_MEMPOOL is this comma. You last proposal of writing #define LWIP_MEMPOOL without the , will not compile because there will be no commas between the elements of the enum.

With a comma you get a valid enum definition

typedef enum {
MEMP_Pool1,
MEMP_Pool2,
MEMP_Pool3,
MEMP_Pool4,
MEMP_MAX
} memp_t

Without a comma you an enum definition without commas with is not syntactically correct

typedef enum {
MEMP_Pool1
MEMP_Pool2
MEMP_Pool3
MEMP_Pool4
MEMP_MAX
} memp_t

If comma here is used to separate the elements of enum then why have written that outside enum in:


#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
typedef enum {
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;

#undef LWIP_MEMPOOL

And also tell me what changes do i need to make in my program of colours in order to make RED, GREEN and BLUE as the elements of enum.


No your example with colour is all wrong, you just define a few symbols you never create enum entries for RED, GREEn and BLUE. That is the code you have written is not equivalent and does not pre-process to

enum colours
{
RED = 10,
GREEN= 20,
BLUE=30,
PINK
};

In particular the contents of c.h is nothing like the contents of memp_std.h, memp_std.h does not #define anything.


When you define an enum normally you have a , between each element. This is a syntactical requirement. The comma at the end of #define LWIP_MEMPOOL is this comma. You last proposal of writing #define LWIP_MEMPOOL without the , will not compile because there will be no commas between the elements of the enum.

With a comma you get a valid enum definition

typedef enum {
MEMP_Pool1,
MEMP_Pool2,
MEMP_Pool3,
MEMP_Pool4,
MEMP_MAX
} memp_t

Without a comma you an enum definition without commas with is not syntactically correct

typedef enum {
MEMP_Pool1
MEMP_Pool2
MEMP_Pool3
MEMP_Pool4
MEMP_MAX
} memp_t

Edited 6 Years Ago by amala.123: n/a

The #define LWIP_MEMPOOL line creates the elements of the enum when combined with memp_std.h. This #define causes every line in memp_std.h to be an element in the enum including the comma.

It doesn't matter where the #define is written, it is a text substitution and gets included where the symbol LWIP_MEMPOOL appears in the code. That is in the code included from memp_std.h.

The process in the preprocessor is something like this (assuming the format for memp_std.h is what I gave in my first post)

#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
typedef enum {
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;
#undef LWIP_MEMPOO
  1. Read line 1: it is a #define, remember the definition and remove it from the code.
  2. Read line 2: there are no preprocessor directives on the line so leave it alone
  3. Read line 3: it is a #include directive, open the given file and copy it into the current source file. At this point the code looks like this
    typedef enum {
    
    LWIP_MEMPOOL(Pool1,100,8,"8 byte pool") 
    LWIP_MEMPOOL(Pool2,100,16,"16 byte pool") 
    LWIP_MEMPOOL(Pool3,100,32,"32 byte pool") 
    LWIP_MEMPOOL(Pool4,100,64,"64 byte pool") 
    
    MEMP_MAX
    } memp_t;
    #undef LWIP_MEMPOO
  4. Read the contents just included starting at line 4
  5. Read line 4: It contains the symbol LWIP_MEMPOOL, the preprocessor has a definition for this symbol so make the text substitution for line 4
  6. Read line 5: It contains the symbol LWIP_MEMPOOL, the preprocessor has a definition for this symbol so make the text substitution for line 5. At this point the code looks like this
    typedef enum {
    
    MEMP_Pool1,
    MEMP_Pool2,
    LWIP_MEMPOOL(Pool3,100,32,"32 byte pool") 
    LWIP_MEMPOOL(Pool4,100,64,"64 byte pool") 
    
    MEMP_MAX
    } memp_t;
    #undef LWIP_MEMPOO
  7. Read line 6: It contains the symbol LWIP_MEMPOOL, the preprocessor has a definition for this symbol so make the text substitution for line 6
  8. Read line 7: It contains the symbol LWIP_MEMPOOL, the preprocessor has a definition for this symbol so make the text substitution for line 7
  9. Read line 8: there are no preprocessor directives on the line so leave it alone
  10. Read line 9: there are no preprocessor directives on the line so leave it alone
  11. Read line 10: there are no preprocessor directives on the line so leave it alone
  12. Read line 11: If contains an #undef statement, remove our record of the symbol LWIP_MEMPOOL and remove the #undef statement from the code.
  13. End: at which point the code looks like this
    typedef enum {
    
    MEMP_Pool1,
    MEMP_Pool2,
    MEMP_Pool3,
    MEMP_Pool4,
    
    MEMP_MAX
    } memp_t;

    This is passed to the compiler to compile.

Through text substitution the , at the end of #define LWIP_MEMPOOL is inserted into the code passed to the compiler so that the enum has a valid format.

Comments
Thanks a lot for your patience and very well explained

OK.....

I finally understood the thing.

Thanks a lot buddy.

If comma here is used to separate the elements of enum then why have written that outside enum in:


#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
typedef enum {
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;

#undef LWIP_MEMPOOL

And also tell me what changes do i need to make in my program of colours in order to make RED, GREEN and BLUE as the elements of enum.

This article has been dead for over six months. Start a new discussion instead.