括号在C中的typeof是什么意思?

时间:2019-01-28 02:07:35

标签: c typeof

我正在研究Linux container_of函数,发现typeof括号的使用确实令人困惑。

这是函数#define container_of(ptr, type, member) ({ \ const typeof( ((type*)0)->member) * __mptr =(ptr);\ (type*)( (char*)__mptr - offsetof(type,member) );}) 的代码:

const typeof( ((type*)0)->member) * __mptr =(ptr);

在第二行,我们有

max(a,b)

我不明白为什么我们在右侧使用括号。

我在线搜索它,发现有类似用法。例如,从https://gcc.gnu.org/onlinedocs/gcc/Typeof.html,我发现了一个函数#define max(a,b) ({ typeof (a) _a = (a); \ typeof (b) _b = (b); \ _a > _b ? _a : _b; })

typeof (a) _a = (a);

在这种情况下,我们确实有类似的用法typeof (a) _a = a;

为什么要在右侧使用括号?我们可以删除右侧的括号以使其Sub Test()吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

通过#define创建的宏执行直接令牌替换。因此,在函数式宏的参数周围使用括号是一种很好的做法,因为它可以防止出现意外问题。

例如:

#define multiply(x, y) x * y

如果您要在此处使用此宏:

int z = multiply(1 + 3, 4 + 5) / 3;

您可能希望z包含值12,但是您会误认为。

它将上面的内容扩展为:

int z = 1 + 3 * 4 + 5 / 3;

这将导致14。使用括号可以避免此问题。如果将其定义为:

#define multiply(x, y) ((x) * (y))

然后上述示例将扩展为:

int z = ((1 + 3) * (4 + 5)) / 3;

将给出预期的结果。

答案 1 :(得分:0)

使用ptr宏时,我们不知道参数将用于container_of。它可能是一个标识符名称,例如MyPointer。但这可能是一个表达式,例如MyArray + 3

宏的常见做法是在替换列表中的参数周围使用括号。例如,如果我们定义square

#define square(x) ((x) * (x))

然后将square(3+4)替换为((3+4) * (3+4)),根据需要将其设置为49。如果我们改为使用:

#define square(x) (x * x)

然后将square(3+4)替换为(3+4 * 3+4),将其评估为3 + 4*3 + 4,即3 + 12 + 4,即19,这是不希望的。

类似地,在您显示的代码中,const typeof( ((type*)0)->member) * __mptr =(ptr);ptr用于初始化名为__mptr的新定义的对象。为了安全起见,在括号内。它不会改变typeof的工作方式。

您不应删除这些括号。在这种特定的情况下,ptr通常不会传递多少内容来破坏没有括号的宏,但是从理论上讲,有一些表达式可能会破坏它。