在glib的gatomic.c
中,有几个函数声明如下所示:
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);
}
字符串
有人能解释一下这段代码到底是做什么的吗?我对这里的几件事感到困惑:
1.函数名g_atomic_int_compare_and_exchange_full
在括号中。这有什么意义
1.这个函数的函数体除了对函数本身的调用外什么都没有,所以这将永远运行并导致堆栈溢出(双关语)。
我完全搞不懂这个函数声明。这到底是怎么回事
5条答案
按热度按时间ivqmmu1c1#
1.函数名g_atomic_int_compare_and_exchange_full在括号中。这有什么意义
将函数名放在方括号中可以避免任何宏扩展,以防存在同名的函数(如宏)。
这意味着,
g_atomic_int_compare_and_exchange_full(...)
将使用宏,而(g_atomic_int_compare_and_exchange_full)(...)
将使用函数。为什么使用这个?不能将宏赋给函数指针。在这种情况下,您可以提供所看到的定义,然后可以使用
字符串
使用函数而不是宏。
1.这个函数的函数体除了对函数本身的调用外什么都没有,所以这将永远运行并导致堆栈溢出(双关语)。
如果查看相关的头文件
gatomic.h
,您将看到确实定义了这样一个宏。在函数体中,函数名周围没有括号。这意味着,使用了宏,并且它不是无限递归。nc1teljy2#
答案在您链接的代码的注解中给出。
以下是编译器宏的集合,可提供对整数和指针大小的值的原子访问。
顺便说一句,和@Gerhardh评论有关。
字符串
定义一个函数
fn
,它的操作也是宏fn
展开的任何内容。在第一次出现
fn
时加上圆括号是为了避免扩展,这显然会导致代码不一致。范例
平方c
型
主要.c
型
使用
gcc -o main main.c sqr.c
编译运行
./main
将打印144
。当然可以了。但更有趣的是,main. c在预处理后看起来像(
gcc -E main.c
)型
(So,
sqr
在这里是一个函数。如果它是宏,现在应该已经展开了)而
sqr.c
预处理给出了型
而这主要的一点:
sqr
是一个函数,它的代码是sqr(x)
的宏扩展。whlutmcx3#
在header
gatomic.h
中定义了一个名为g_atomic_int_compare_and_exchange_full
的宏:字符串
还有一个同名函数。
当名称用括号括起来时,
型
那么编译器不能将其视为宏。
也就是说,你有一个函数定义,其中使用了一个与函数名称相同的宏。
下面是一个演示程序:
型
注意声明符(包括函数声明符)可能会被括号括起来。
从定义声明符的C语法中:
型
下面是一个二维数组的声明,括号中有封闭声明符:
型
尽管括号显然是多余的。
2jcobegt4#
正如其他人所说,这允许将某个对象定义为类似函数的宏和真实的函数。
你为什么要这么做?我可以看到几个原因。
1.向后兼容性。库作者可能出于性能或灵活性原因而从真实的函数切换到类函数宏,但仍希望保持与调用实函数的现有二进制文件的兼容性。
1.与其他编程语言兼容。用C语言编写的宏只能在C和C++等语言中有效使用,这些语言或多或少都是C的扩展。真实的函数可以从任何支持C调用约定的语言中调用。
1.真实的函数可以与函数指针一起使用,而类似函数的宏则不能。
ej83mcc05#
您提供的代码不是完整的函数定义,而是实际函数
g_atomic_int_compare_and_exchange_full
的“ Package 器”或“函数别名”。让我们分解一下这里发生的事情:1.函数别名:您提供的代码为函数
g_atomic_int_compare_and_exchange_full
创建了一个别名。别名是用括号括住函数名创建的,后面是函数的参数列表和函数体。此技术通常在宏中用于定义类似函数的宏。在本例中,宏似乎与实际函数有别名。1.递归调用:你是对的,代码,因为它是,似乎导致一个递归调用,这将导致堆栈溢出。然而,这个代码片段可能是一个更大的上下文的一部分,函数
g_atomic_int_compare_and_exchange_full
的真实的定义应该在其他地方。真实的的函数应该有一个正确的实现,而不是对自身的递归调用。为了更清楚地说明这一点,
g_atomic_int_compare_and_exchange_full
的实际实现应该在其他地方定义,它可能看起来像这样:字符串