这是我直接从CImg库中获取的一段代码,试图了解它在
中的实际工作原理宏在第628行定义为
#define cimg_for(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size(); (ptrs--)>(img)._data; )
和CImg在第9035行中有一个名为this的构造函数
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; }
}
我相信这是宏将如何使用,但想要第二个意见
for (T_ptrs *ptrs = (img)._data + (img).size(); (ptrs--)>(img)._data; )
*ptrd = (T)*(--ptrs);
整个混乱是因为两个ptrs变量
答案 0 :(得分:4)
预处理器不知道C.它对令牌进行操作。 for
是一个像rof
这样的标记,只要预处理器知道。
那么,宏之后的位?预处理器不知道这是for
语句的一部分。一旦看到)
的结束cimg_for(
,就完成了。没有进一步的替代。
在您的情况下,cimg_for(*this,ptrd,T)
设置:
img
至this
ptrs
至ptrd
T_ptrs
至T
(ptrs类型)这段代码很奇怪,顺便说一下:如果你有C ++,你就不需要这些宏观攻击。
答案 1 :(得分:2)
这看起来不像C,但这里是宏如何在C中工作:
在整个代码中搜索宏关键字。在编译之前,宏关键字将被其定义替换。如果它是带参数的宏,则传递的参数将替换为定义中的参数。
在您的情况下,:
cimg_for(*this,ptrd,T)
将变成以下内容:
for (T * ptrd = (*this)._data + (*this).size(); (ptrd--)>(*this)._data; )
在撰写时,我首先复制了定义,然后用img
替换每个*this
内部定义,然后用ptrs
替换每个ptrd
,最后每个{{} {1}} T_ptrd
。这就是宏定义告诉我要做的事情,这也是预处理器在编译之前所做的事情。
在那个宏之后,有一个语句,所以最后,循环如下所示:
T
答案 2 :(得分:1)
宏不是函数。它们基本上是一个精心设计的“搜索和替换”。预处理器逐字地替换了宏的主体(在声明宏的范围内)与宏的主体的位置。
一些gatchas:因为宏不像函数,所以这样的事情变得危险
#define SQUARE(A) A*A
int i = 2;
int j = SQUARE(++i);
k == 9 // oops!
或者
int i = SQUARE(IncrediblyExpensiveFuncionThatReturnsAnInt());
这个巨大的函数被调用两次。一次为宏中的每个A
有关宏的危险及其工作原理的详细信息,请查看this
答案 3 :(得分:1)
这个
#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);
变为
for (T *ptrd = (*this)._data + (*this).size(); (ptrd--)>(*this)._data; )
*ptrd = (T)*(--ptrs);