鉴于:
int func(int x, int y) { /* ... */ }
表达式func
是函数类型。具体来说,它是 type int(int, int)
,这是 C 中“函数int
返回两个参数的类型”的语法int
。(你不会经常看到这种特定的语法,因为直接引用函数类型并不常见。)
在大多数情况下,函数类型的表达式被隐式转换为指向函数的指针;在这种情况下,指针的类型是int(*)(int, int)
。
不发生这种隐式转换的上下文是:
当表达式是 unary 的操作数时&
;在这种情况下,&func
产生函数的地址(就像func
它本身通常所做的那样);和
当表达式是 的操作数时sizeof
。没有这个例外,sizeof func
将产生一个函数指针的大小。相反,它是违反约束的,需要编译器进行诊断。
(附注:在函数调用中使用函数名称时确实会发生这种转换。()
“运算符”(标准不这么称呼它)需要指向函数类型的前缀。)
gcc 恰好有一个非标准的扩展;它允许对函数指针和 type 进行指针运算void*
,其作用类似于指针上的指针运算char*
(即,它以字节为单位进行运算)。不幸的是,恕我直言,gcc 通过 kludge 做到了这一点,将函数类型和类型的大小设置void
为 1。这就是你得到sizeof func == 1
; 如果您启用一种标准的符合模式(例如,gcc -std=c99 -pedantic
),您将收到警告。
顺便说一句,不要%d
用于打印sizeof
. sizeof
产生类型的结果size_t
。如果您的实现支持它(C99 或更高版本),请使用%zu
; 如果没有,您需要使用强制转换将size_t
值显式转换为可以打印的内容。例如:
printf("%lu\n", (unsigned long)sizeof &func);