【GNU笔记】【C扩展系列】构造函数调用Constructing Function Calls

【GNU笔记】【C扩展系列】构造函数调用Constructing Function Calls

构造函数调用 Constructing Function Calls

使用下面描述的内置函数,你可以记录一个函数接收到的参数,并以相同的参数调用另一个函数,而不知道参数的数量或类型。

你也可以记录该函数调用的返回值,然后返回该值,而不知道该函数试图返回的数据类型(只要你的调用者期望有该数据类型)。

然而,这些内置函数可能与一些复杂的特性或语言的其他扩展发生不良的交互。因此,不建议在非常简单的函数之外使用它们,因为它们只是作为参数的转发者。

  • 内置函数:void * __builtin_apply_args ()

    这个内置函数返回一个指向数据的指针,该指针描述如何用传递给当前函数的相同参数执行调用。

    该函数将arg指针寄存器、结构值地址和所有可能用于向函数传递参数的寄存器保存在堆栈上分配的一个内存块中。然后,它返回该块的地址。

  • 内置函数:void * __builtin_apply (void (* function )(), void * arguments , size_t size )

    这个内置函数使用由argumentssize描述的参数的拷贝来调用function

    参数的值应该是__builtin_apply_args返回的值。参数size指定了堆栈参数数据的大小,单位是字节。

    这个函数返回一个指向数据的指针,该数据描述如何返回function返回的任何值。数据保存在堆栈上分配的内存块中。

    计算size的正确值并不总是那么简单。这个值用于__builtin_apply计算应推入堆栈上并从传入的参数区复制的数据量。

  • 内置函数:void __builtin_return (void * result )

    这个内置函数返回由包含函数的result所描述的值。你应该为result指定一个由__builtin_apply返回的值。

  • 内置功能: __builtin_va_arg_pack ()

    这个内置函数表示内联函数的所有匿名参数。它只能用在总是内联的内联函数中,从不作为单独的函数编译,例如那些使用__attribute__ ((__always_inline__))__attribute__ ((__gnu_inline__))extern 内联函数。它必须只作为最后一个参数传递给其他一些具有可变参数的函数。当不希望使用预处理器宏时,这对于为可变参数的函数编写小型封装内联是非常有用的。例如:

extern int myprintf (FILE *f, const char *format, ...);
extern inline __attribute__ ((__gnu_inline__)) int
myprintf (FILE *f, const char *format, ...)
{
int r = fprintf (f, "myprintf: ");
  if (r < 0)
  return r;
  int s = fprintf (f, format, __builtin_va_arg_pack ());
if (s < 0)
    return s;
return r + s;
}
  
  • 内置函数:size_t __builtin_va_arg_pack_len ()

    这个内置函数返回内联函数的匿名参数的数量。它只能用在总是内联的内联函数中,从不作为单独的函数编译,例如那些使用 __attribute__ ((__always_inline__))__attribute__ ((__gnu_inline__)) extern 内联函数。例如下面为优化的代码做了开放参数的链接或运行时检查。

    例如,下面对优化代码的开放参数进行链接或运行时检查:

    #ifdef __OPTIMIZE__
    extern inline __attribute__((__gnu_inline__)) int
    myopen (const char *path, int oflag, ...)
    {
      if (__builtin_va_arg_pack_len () > 1)
        warn_open_too_many_arguments ();
    
      if (__builtin_constant_p (oflag))
        {
          if ((oflag & O_CREAT) != 0 && __builtin_va_arg_pack_len () < 1)
            {
              warn_open_missing_mode ();
              return __open_2 (path, oflag);
            }
          return open (path, oflag, __builtin_va_arg_pack ());
        }
    
      if (__builtin_va_arg_pack_len () < 1)
        return __open_2 (path, oflag);
    
      return open (path, oflag, __builtin_va_arg_pack ());
    }
    #endif
    

[参考资料]

6.6 Constructing Function Calls

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值