符合 C11 标准的编译器接受的替代函数指针语法
Alternative function pointer syntax accepted by compilers with C11 standard
我不确定这个函数指针类型声明语法,但它确实有效。语法就像声明一个常规的旧函数一样。
typedef struct Element GetChildCallback(void *userdata, usize parent, usize child_no);
我找不到任何关于它符合标准的程度或它可能有哪些缺点的信息。
我认为这只适用于 typedef,所以我更进一步发现这也适用于常规函数参数:
extern inline void dmpstrn(const char *t, usize n, int printer(const char *fmt, ...));
inline void dmpstrn(const char *t, usize n, int printer(const char *fmt, ...)) {
usize len = strlen(t) > n ? n : strlen(t);
printer("\"");
for (usize i = 0; i < len; i += 1) {
if (t[i] == '\n')
printer("\n");
else
printer("%c", t[i]);
}
printer("\"\n");
}
// ...
int main() {
dmpstrn("Hello\nworld", UINT64_MAX, printf);
}
但这对变量不起作用
int printer(const char *fmt, ...) = printf; // Invalid
好像它不是函数指针而是实际函数,但它是什么意思?
用作函数参数的函数声明由编译器隐式调整为指向函数类型的指针。
来自 C 标准(6.7.6.3 函数声明符(包括原型))
8 A declaration of a parameter as ‘‘function returning type’’ shall be
adjusted to ‘‘pointer to function returning type’’, as in 6.3.2.1
例如这两个函数声明
void f( void( int ) );
和
void f( void ( * )( int ) );
声明同一个函数。
另一方面(6.3.2.1 左值、数组和函数指示符)
4 A function designator is an expression that has function type.
Except when it is the operand of the sizeof operator65) or the unary &
operator, a function designator with type ‘‘function returning type’’
is converted to an expression that has type ‘‘pointer to function
returning type’’
这是一个演示程序。
#include <stdio.h>
typedef void F( int );
F display;
void g( F );
void g( F *f )
{
int x = 10;
f( x );
}
void display( int x )
{
printf( "x = %d\n", x );
}
int main(void)
{
F *fp = display;
g( fp );
return 0;
}
程序输出为
x = 10
调查程序。
注意,例如这个 typedef
typedef void F( int );
可以等效地重写为
void typedef F( int );
typedef struct Element GetChildCallback(void *userdata, usize parent, usize child_no);
这定义GetChildCallback
为实际的“函数类型”,它不同于指向函数类型的指针。这可以用于声明函数或形成指向函数类型的指针,但不能用于定义函数:
GetChildCallback MyButtonCB; /* OK, declares function */
GetChildCallback MyResizeCB {} /* ERROR, bad syntax */
struct Element MyButtonCB(void *, usize, usize) {} /* OK */
GetChildCallback cb1 = MyButtonCB; /* ERROR, bad function definition */
GetChildCallback* cb2 = MyButtonCB; /* OK */
void add_callback(Button* button, GetChildCallback* cb); /* OK */
当函数类型用作函数参数时,它默默地成为函数类型的指针,就像数组参数类型成为元素指针类型一样。所以你的例子
inline void dmpstrn(const char *t, usize n, int printer(const char *fmt, ...)) {
和
的意思一样
inline void dmpstrn(const char *t, usize n, int (*printer)(const char *fmt, ...)) {
包括函数体中的 printer
是指向函数的指针,因此例如 (&printer)
与 (printer)
的行为不同。
我不确定这个函数指针类型声明语法,但它确实有效。语法就像声明一个常规的旧函数一样。
typedef struct Element GetChildCallback(void *userdata, usize parent, usize child_no);
我找不到任何关于它符合标准的程度或它可能有哪些缺点的信息。
我认为这只适用于 typedef,所以我更进一步发现这也适用于常规函数参数:
extern inline void dmpstrn(const char *t, usize n, int printer(const char *fmt, ...));
inline void dmpstrn(const char *t, usize n, int printer(const char *fmt, ...)) {
usize len = strlen(t) > n ? n : strlen(t);
printer("\"");
for (usize i = 0; i < len; i += 1) {
if (t[i] == '\n')
printer("\n");
else
printer("%c", t[i]);
}
printer("\"\n");
}
// ...
int main() {
dmpstrn("Hello\nworld", UINT64_MAX, printf);
}
但这对变量不起作用
int printer(const char *fmt, ...) = printf; // Invalid
好像它不是函数指针而是实际函数,但它是什么意思?
用作函数参数的函数声明由编译器隐式调整为指向函数类型的指针。
来自 C 标准(6.7.6.3 函数声明符(包括原型))
8 A declaration of a parameter as ‘‘function returning type’’ shall be adjusted to ‘‘pointer to function returning type’’, as in 6.3.2.1
例如这两个函数声明
void f( void( int ) );
和
void f( void ( * )( int ) );
声明同一个函数。
另一方面(6.3.2.1 左值、数组和函数指示符)
4 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator65) or the unary & operator, a function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’
这是一个演示程序。
#include <stdio.h>
typedef void F( int );
F display;
void g( F );
void g( F *f )
{
int x = 10;
f( x );
}
void display( int x )
{
printf( "x = %d\n", x );
}
int main(void)
{
F *fp = display;
g( fp );
return 0;
}
程序输出为
x = 10
调查程序。
注意,例如这个 typedef
typedef void F( int );
可以等效地重写为
void typedef F( int );
typedef struct Element GetChildCallback(void *userdata, usize parent, usize child_no);
这定义GetChildCallback
为实际的“函数类型”,它不同于指向函数类型的指针。这可以用于声明函数或形成指向函数类型的指针,但不能用于定义函数:
GetChildCallback MyButtonCB; /* OK, declares function */
GetChildCallback MyResizeCB {} /* ERROR, bad syntax */
struct Element MyButtonCB(void *, usize, usize) {} /* OK */
GetChildCallback cb1 = MyButtonCB; /* ERROR, bad function definition */
GetChildCallback* cb2 = MyButtonCB; /* OK */
void add_callback(Button* button, GetChildCallback* cb); /* OK */
当函数类型用作函数参数时,它默默地成为函数类型的指针,就像数组参数类型成为元素指针类型一样。所以你的例子
inline void dmpstrn(const char *t, usize n, int printer(const char *fmt, ...)) {
和
的意思一样inline void dmpstrn(const char *t, usize n, int (*printer)(const char *fmt, ...)) {
包括函数体中的 printer
是指向函数的指针,因此例如 (&printer)
与 (printer)
的行为不同。