And*_*eas 89 c macros function glib function-declaration
在gatomic.cglib 中,有几个函数声明如下所示:
gboolean
(g_atomic_int_compare_and_exchange_full) (gint *atomic,
gint oldval,
gint newval,
gint *preval)
{
return g_atomic_int_compare_and_exchange_full (atomic, oldval, newval, preval);
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下这段代码到底是做什么的吗?我对这里的几件事感到困惑:
函数名称g_atomic_int_compare_and_exchange_full位于括号内。这有什么意义呢?
该函数的主体显然只包含对函数本身的调用,因此这将永远运行并导致堆栈溢出(双关语)。
我根本无法理解这个函数声明。这里究竟发生了什么?
Ger*_*rdh 121
- 函数名称 g_atomic_int_compare_and_exchange_full 在括号中。这有什么意义呢?
将函数名称放在括号中可以避免任何宏扩展,以防存在同名的类似宏的函数。
这意味着,g_atomic_int_compare_and_exchange_full(...)将使用宏,同时(g_atomic_int_compare_and_exchange_full)(...)将使用函数。
为什么要使用这个?您不能将宏分配给函数指针。在这种情况下,您可以提供您所看到的定义,然后您可以使用
ptr = g_atomic_int_compare_and_exchange_full;
Run Code Online (Sandbox Code Playgroud)
使用函数而不是宏。
- 该函数的主体显然只包含对函数本身的调用,因此这将永远运行并导致堆栈溢出(双关语)。
如果您查看关联的标头,gatomic.h您会发现确实定义了这样的宏。并且在函数体中,函数名称周围没有使用括号。这意味着,使用了宏并且它不是无限递归。
chr*_*slg 49
答案在您链接的代码的注释中给出。
以下是编译器宏的集合,用于提供对整数和指针大小的值的原子访问。
顺便说一句,与@Gerhardh 评论相关。
int (fn)(int param){
fn(param);
}
Run Code Online (Sandbox Code Playgroud)
定义一个函数fn,其操作也是宏fn扩展的任何内容。
第一次出现的括号fn是为了避免扩展这个,这显然会导致代码不一致。
例子
sqr.c
#define sqr(x) x*x
int (sqr)(int x){
return sqr(x);
}
Run Code Online (Sandbox Code Playgroud)
主程序
#include <stdio.h>
extern int sqr(int);
int main(){
printf("%d\n", sqr(12));
}
Run Code Online (Sandbox Code Playgroud)
编译用gcc -o main main.c sqr.c
运行./main打印144。当然。
但更有趣的是,经过预处理后的 main.c 看起来像 ( gcc -E main.c)
extern int sqr(int);
int main(){
printf("%d\n", sqr(12));
}
Run Code Online (Sandbox Code Playgroud)
(所以,sqr这里是一个函数。如果它是一个宏,那么它现在已经被扩展了)
sqr.c预处理给出
int (sqr)(int x){
return x*x;
}
Run Code Online (Sandbox Code Playgroud)
要点是:sqr是一个函数,其代码是 的宏展开sqr(x)。
Vla*_*cow 19
有一个宏,其名称g_atomic_int_compare_and_exchange_full在 header 中定义gatomic.h:
#define g_atomic_int_compare_and_exchange_full(atomic, oldval, newval, preval) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
G_STATIC_ASSERT (sizeof *(preval) == sizeof (gint)); \
(void) (0 ? *(atomic) ^ (newval) ^ (oldval) ^ *(preval) : 1); \
*(preval) = (oldval); \
__atomic_compare_exchange_n ((atomic), (preval), (newval), FALSE, \
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) \
? TRUE : FALSE; \
}))
Run Code Online (Sandbox Code Playgroud)
并且有一个同名的函数。
当名称像这里一样用括号括起来时,
gboolean
(g_atomic_int_compare_and_exchange_full) (gint *atomic,
gint oldval,
gint newval,
gint *preval)
Run Code Online (Sandbox Code Playgroud)
那么编译器就不能将其视为宏。
也就是说,您有一个函数定义,其中使用了与函数名称相同的宏。
这是一个演示程序:
#include <stdio.h>
#define from( x )( x ) * ( x )
int (from)( int x ) { return from( x ); }
int main( void )
{
printf( "%d\n", (from)( 10 ) );
}
Run Code Online (Sandbox Code Playgroud)
请注意,声明符(包括函数声明符)可以用括号括起来。
从定义声明符的 C 语法来看:
direct-declarator:
identifier
( declarator )
Run Code Online (Sandbox Code Playgroud)
下面是一个二维数组的声明,其中声明符括在括号中:
int ( ( ( a )[10] )[10] );
Run Code Online (Sandbox Code Playgroud)
尽管括号显然是多余的。
| 归档时间: |
|
| 查看次数: |
8385 次 |
| 最近记录: |