【GNU笔记】【C扩展系列】构造函数调用Constructing Function Calls
构造函数调用 Constructing Function Calls
使用下面描述的内置函数,你可以记录一个函数接收到的参数,并以相同的参数调用另一个函数,而不知道参数的数量或类型。
你也可以记录该函数调用的返回值,然后返回该值,而不知道该函数试图返回的数据类型(只要你的调用者期望有该数据类型)。
然而,这些内置函数可能与一些复杂的特性或语言的其他扩展发生不良的交互。因此,不建议在非常简单的函数之外使用它们,因为它们只是作为参数的转发者。
-
内置函数:void * __builtin_apply_args ()
这个内置函数返回一个指向数据的指针,该指针描述如何用传递给当前函数的相同参数执行调用。
该函数将arg指针寄存器、结构值地址和所有可能用于向函数传递参数的寄存器保存在堆栈上分配的一个内存块中。然后,它返回该块的地址。
-
内置函数:void * __builtin_apply (void (* function )(), void * arguments , size_t size )
这个内置函数使用由arguments和size描述的参数的拷贝来调用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