Question

This is a piece of code that i directly took from CImg library trying to understand how it actually works inside

Macro is defined in line 628 as

#define cimg_for(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size(); (ptrs--)>(img)._data; )

and CImg has a constructor called like this in line number 9035

template<typename t>
CImg(const t *const values, const unsigned int size_x, const unsigned int size_y=1,
     const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false):_is_shared(false) {
  if (is_shared) {
    _width = _height = _depth = _spectrum = 0; _data = 0;
    throw CImgArgumentException(_cimg_instance
                                "CImg() : Invalid construction request of a (%u,%u,%u,%u) shared instance from a (%s*) buffer "
                                "(pixel types are different).",
                                cimg_instance,
                                size_x,size_y,size_z,size_c,CImg<t>::pixel_type());
  }
  const unsigned int siz = size_x*size_y*size_z*size_c;
  if (values && siz) {
    _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
    try { _data = new T[siz]; } catch (...) {
      _width = _height = _depth = _spectrum = 0; _data = 0;
      throw CImgInstanceException(_cimg_instance
                                  "CImg() : Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
                                  cimg_instance,
                                  cimg::strbuffersize(size_x*size_y*size_z*size_c*sizeof(T)),size_x,size_y,size_z,size_c);

    }
    const t *ptrs = values + siz; cimg_for(*this,ptrd,T) *ptrd = (T)*(--ptrs);
  } else { _width = _height = _depth = _spectrum = 0; _data = 0; }
}

I believe this is how macro will be used, but would like a second opinion

for (T_ptrs *ptrs = (img)._data + (img).size(); (ptrs--)>(img)._data; )
     *ptrd = (T)*(--ptrs);

the entire confusion is because of two ptrs variable

Was it helpful?

Solution 2

This doesn't look like C, but here's how macros work in C:

Macro keyword is searched throughout the code. Macro keyword is replaced with its definition prior to compilation. If it is a macro with arguments, the passed arguments are replaced with the ones inside the definition.

In your case, the:

cimg_for(*this,ptrd,T)

Will be turned into the following:

for (T * ptrd = (*this)._data + (*this).size(); (ptrd--)>(*this)._data; )

While writing that, I have first copied the definition, then replaced each img inside definition with *this, then replaced each ptrs with ptrd, and lastly each T_ptrd with T. That's what macro definition told me to do, that's also what preprocessor does prior to compilation.

After that macro thing, there is a statement, so in the end, the loop looks like the following:

for (T * ptrd = (*this)._data + (*this).size(); (ptrd--)>(*this)._data; )
    *ptrd = (T)*(--ptrs);

OTHER TIPS

The preprocessor doesn't know C. It operates on tokens. for is a token like rof, as far as the preprocessor knows.

So, the bit that follows the macro? The preprocessor doesn't know that's part of a for statement. Once it's seen the closing ) of cimg_for(, it's done. No further replacements.

In your case, cimg_for(*this,ptrd,T) sets:

  • img to this
  • ptrs to ptrd
  • T_ptrs to T (Type of ptrs)

This code is weird, BTW: If you have C++, you don't need these macro hacks.

Macros aren't functions. They are basically an elaborate "search and replace". The preprocessor literally replaces where ever it finds the macro (within the scope that the macro is declared) with the body of the macro.

Some gatchas: Because macros are not like functions, things like this become dangerous

#define SQUARE(A) A*A

int i = 2;
int j = SQUARE(++i);

k == 9 // oops!

or this

int i = SQUARE(IncrediblyExpensiveFuncionThatReturnsAnInt());

That huge function gets called twice. Once for each A in the macro

For more info on the dangers of macros and how they work, check out this

This

#define cimg_for(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size(); (ptrs--)>(img)._data; )
cimg_for(*this,ptrd,T) *ptrd = (T)*(--ptrs);

becomes

for (T *ptrd = (*this)._data + (*this).size(); (ptrd--)>(*this)._data; )
  *ptrd = (T)*(--ptrs);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top