GCC的C语言扩展(四)

返回值的复合语句:

复合语句是大括号包围的一个语句块,在复合语句内你可以声明自己的变量,如下例所示:

{
    int a = 5;
    int b;
    b = a + 5;
}
在GNU C中,圆括号包围的复合语句可以生成返回值,返回的结果的类型和值是复合语句的最后一句的类型和值。如下例所示,它会返回值8:
rslt = ({
            int a = 5;
            int b;
            b = a + 3;
       });

下面的宏返回一个等于或大于x的偶数

#define even(x)    (2 * ((x) / 2) == (x) ? (x) : (x) + 1)

在使用even(i++)这样的表达式时应付产生副用,下面的宏实现同样的功能,使用了GCC的扩展,在复合语句里声明了一个临时变量:

#define evenint(x)    \

      ({int y = x; \

        (2 * (y / 2) == y ? y : y + 1); \

     })

注意:这种功能扩展在C++中会产生问题。问题来自于宏内部的临时变量的析构函数,临时变量会在赋值前被析构。

条件操作数的省略:

如下例中的条件表达式:

x = y ? y : z;

在GCC扩展中,可以写成下面的形式:

x = y ? : z;

构造函数调用

GCC提供了三个内置函数用于将当前函数的参数直接传递给另一个函数,并将另一个函数的执行结果返回给调用者。

下面的函数找到并返回参数的信息:

void *__builtin_apply_args(void);

一旦获得了参数的信息,可以用下面的函数去构造调用所需要的栈(stack)并调用该函数。

void *__builtin_apply(void (*func)(), void *arguments, int size);

第一个参数是要调用函数的地址,第二个是由__builtin_apply_args()返回调用参数的信息,用于构造调用的参数。size参数为从当前堆栈框架(stack frame)复制到新堆栈框架中的字节数,该值应该足够大,以容纳调用传送的参数和返回值。

一旦调用完成,可以用下面的函数将func的执行结果返回给调用者。

__builtin_return(void *result);

result为__builtin_apply返回的值。

下面的程序调用了passthrough(),它通过内建的三个函数来调用average()函数,并将其结果返回给它的调用者。

/* args.c */
#include <stdio.h>
int passthrough();
int average();

int main(int argc, char *argv[])
{
    int result;
    result = passthrough(1, 7, 10);
    printf("result = %d\n", result);
    return 0;
}

int passthrough(int a, int b, int c)
{
    void *record;
    void *playback;
    void (* fn)() = (void (*)()) average;

    record = __builtin_apply_args();
    playback = __builtin_apply(fn, record, 128);
    __builtin_return(playback);
}

int average(int a, int b, int c) 
{
    return ((a + b + c) / 3);

如果用省略号创建变长参数列表,返回值指向void指针,函数passthrough()只需要知道要函数的地址,就可以调用任何函数而返回任何类型。

 

转载于:https://my.oschina.net/senmole/blog/51997

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值