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

括号在C的typeof中是什么意思?,c,typeof,C,Typeof,我正在研究Linux的container\u of函数,我发现typeof的括号的用法真的很混乱 以下是函数容器的代码: #define container_of(ptr, type, member) ({ \ const typeof( ((type*)0)->member) * __mptr =(ptr);\ (type*)( (char*)__mptr - offsetof(type,member) );}) 在第二行,我们有 consttypeof((type*)

我正在研究Linux的container\u of函数,我发现typeof的括号的用法真的很混乱

以下是函数
容器的代码

#define container_of(ptr, type, member) ({ \
    const typeof( ((type*)0)->member) * __mptr =(ptr);\
    (type*)( (char*)__mptr - offsetof(type,member) );})
在第二行,我们有

consttypeof((type*)0)->member)*\uu mptr=(ptr)

我不明白为什么我们在右边用括号

我在网上搜索,找到了一些类似的用法。例如,从中,我找到了一个函数
max(a,b)

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

为什么要在右边用括号?我们是否可以去掉右边的括号,使其
typeof(a)_a=a


提前谢谢

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

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

#define square(x) ((x) * (x))
然后将
正方形(3+4)
替换为
((3+4)*(3+4))
,根据需要为49。如果我们改为使用:

#define square(x) (x * x)
然后将
正方形(3+4)
替换为
(3+4*3+4)
,其将被评估为
3+4*3+4
,即
3+12+4
,即19,这是不需要的

类似地,在您显示的代码中,
consttypeof((type*)0)->member)*\uu mptr=(ptr)
ptr
用于初始化新定义的名为
\uu mptr
的对象。为了安全起见,放在括号里。它不会改变
类型的操作方式


不应删除这些括号。在这个特定的上下文中,通常不会为
ptr
传递太多的内容来中断没有括号的宏,但是有一些表达式在理论上可能会中断宏。

我们不知道当使用
宏的
容器\u时,参数将用于
ptr
。它可能是一个标识符名称,如
MyPointer
。但它可能是一个表达式,比如
MyArray+3

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

#define square(x) ((x) * (x))
然后将
正方形(3+4)
替换为
((3+4)*(3+4))
,根据需要为49。如果我们改为使用:

#define square(x) (x * x)
然后将
正方形(3+4)
替换为
(3+4*3+4)
,其将被评估为
3+4*3+4
,即
3+12+4
,即19,这是不需要的

类似地,在您显示的代码中,
consttypeof((type*)0)->member)*\uu mptr=(ptr)
ptr
用于初始化新定义的名为
\uu mptr
的对象。为了安全起见,放在括号里。它不会改变
类型的操作方式

不应删除这些括号。在这个特定的上下文中,通常不会为
ptr
传递太多不带括号的中断宏的信息,但是理论上有一些表达式可能会中断宏。

通过
\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;
这将给出预期的结果。

通过
#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;

这将产生预期的结果。

谢谢!这就解决了问题!非常感谢。这就解决了问题!