用指针理解C宏

时间:2014-12-26 22:43:16

标签: c pointers macros

我是一名Java开发人员,我对C宏的语法不是很熟悉。我正在研究Deitel& Deitel书,但它没有帮助。

我无法理解这个宏的含义:

#define _GetFrontItem(d,q)  ( (d)->itemCache + ( (q)*(d)->block_size +  \
                              (d)->offset[q] % (d)->block_size )*(d)->itemSize)

d是指向结构的指针,qsize_t

宏使用in this file

你能帮我理解一下吗?这个宏完成了什么?为什么写它的方式?有没有更清晰的方法来编写这个宏?

3 个答案:

答案 0 :(得分:5)

我不得不说,这是一个该死的丑陋宏。继续前进。

宏所做的是计算struct的“item cache”(无论是什么)的索引,并返回指向它的指针:(d->itemCache + something)等同于&d->itemCache[something]

宏因此等同于以下内联函数(从Google匹配here中提取的标识符):

static inline char *_GetFrontItem(Data *d, size_t q) {
    return &d->itemCache[
        d->itemSize * (q * d->block_size + d->offset[q] % d->block_size)
    ];
}

......这更容易被理解。为什么它首先是一个宏可能是因为这是遗留代码,从过去的内联函数根本就不存在。

答案 1 :(得分:4)

每当您在源代码中编写_GetFrontItem(d,q)时,预处理器就会将其替换为此行

(d)->itemCache + ( (q)*(d)->block_size + (d)->offset[q] % (d)->block_size )*(d)->itemSize

所以这里d必须是->的结构的指针。 更多d指向的结构必须具有至少3个成员,如下所示itemCacheblock_size和数据类型为offset的数组

此宏除了替换计算外什么都不做。

另一件事,在第一行:

#define _GetFrontItem(d,q) ( (d)->itemCache + ( (q)*(d)->block_size + \

注意该行末尾的反斜杠\。在定义宏时使用此字符(当然在行的末尾)将允许您继续在第二行写入,就像在第一行中继续写一样。它可以被视为使代码可读而不复杂的工具!!

答案 2 :(得分:3)

在这种情况下,d是指向struct对象的指针。该struct对象包含一个缓冲区d->itemCache(很可能是unsigned char s的数组)。缓冲区实际上表示一个较大对象的数组,每个对象由d->itemSize个字节组成。因此,为了获得指向此数组中对象编号i的指针,您必须评估以下表达式

d->itemCache + i * d->itemSize

这正是你的宏所做的,除了元素索引i通过参数q评估为

q * d->block_size + d->offset[q] % d->block_size

这可能取决于相关数据结构的细节。

为了使这个宏更具可读性,可以将其分成几个宏

#define _GetItem(d, i)  ((d)->itemCache + (i) * (d)->itemSize)
#define _GetFrontIndex(d, q) ((q) * (d)->block_size + (d)->offset[q] % (d)->block_size)
#define _GetFrontItem(d, q) _GetItem(d, _GetFrontIndex(d, q))