C中的函数名是什么类型的?

C中的函数名是什么类型的?,c,function,C,Function,我一直明白在C语言中,func和&func是等价的。我假设它们都应该是指针类型,在我的Win64系统上是8字节。然而,我只是尝试了一下: #include <stdio.h> int func(int x, int y) { printf("hello\n"); } int main() { printf("%d, %d\n", sizeof(&func), sizeof(func)); return 0; } #包括 int func(int

我一直明白在C语言中,
func
&func
是等价的。我假设它们都应该是指针类型,在我的Win64系统上是8字节。然而,我只是尝试了一下:

#include <stdio.h>

int func(int x, int y)
{
    printf("hello\n");
}

int main()
{
    printf("%d, %d\n", sizeof(&func), sizeof(func));
    return 0;
}
#包括
int func(int x,int y)
{
printf(“hello\n”);
}
int main()
{
printf(“%d,%d\n”,sizeof(&func),sizeof(func));
返回0;
}
期望得到输出
8,8
,却意外得到
8,1

为什么会这样?什么类型的函数是
func
?它似乎属于
char
类型或类似类型。
这是怎么回事

我用gcc-std=c99编译了这篇文章,如果它有区别的话

C中的函数名是什么类型的

函数名或函数指示符具有函数类型。在表达式中使用时,除了它是
sizeof
&
运算符的操作数外,它从类型“函数返回类型”转换为类型“指向函数返回类型的指针”。(这在C99,6.3.2.1p4中有规定)

现在

sizeof(func)

C无效,因为函数类型的操作数不允许使用
sizeof
。这在
sizeof
运算符的约束中指定:

(C99,6.5.3.4p1约束)“sizeof运算符不得应用于具有函数类型或不完整类型的表达式、此类类型的括号名称或指定位字段成员的表达式。”

但是

sizeof(func)

在GNUC中是允许的

GNU C中有一个允许它的GNU扩展,在GNU C中有一个函数类型的操作数产生
1

6.23空指针和函数指针的算法

在void和函数类型上也允许使用[…]sizeof,并返回1

C中的函数名是什么类型的

它属于功能类型。

我一直明白在C语言中,
func
&func
是等价的

嗯,它们不是“等价物”。然而,函数确实会衰减为指向函数的指针

我认为它们都应该是指针类型

这是一个错误的假设

期望得到输出8,8却意外地得到了8,1。为什么会这样

因为1。这是UB如果它编译,2。它甚至不应该首先编译,因此,您的程序可以自由执行任何操作。

给定:

int func(int x, int y) { /* ... */ }
表达式
func
属于函数类型。具体来说,它的类型是
int(int,int)
,这是C对“函数”类型的语法,该类型有两个
int
参数返回
int
(您不会经常看到这种特殊的语法,因为直接引用函数类型并不常见。)

在大多数上下文中,函数类型的表达式隐式转换为指向函数的指针;在本例中,指针的类型为
int(*)(int,int)

不发生此隐式转换的上下文包括:

  • 当表达式是一元
    &
    的操作数时;在这种情况下,
    &func
    产生函数的地址(就像
    func
    本身通常产生的那样);以及

  • 当表达式是
    sizeof
    的操作数时。如果没有此异常,
    sizeof func
    将产生函数指针的大小。相反,它是一种约束冲突,需要编译器进行诊断

  • (旁注:在函数调用中使用函数名时,会发生此转换。
    ()
    “运算符”(标准不调用该运算符)需要指向函数类型的指针前缀。)

    gcc恰好有一个非标准扩展;它允许对函数指针和类型
    void*
    进行指针运算,就像对
    char*
    指针进行指针运算一样(即,它以字节为单位操作)。不幸的是,IMHO,gcc通过一个乱码实现了这一点,将函数类型和类型的大小
    void
    设置为1。这就是为什么您会得到
    sizeof func==1
    ;如果您启用一个标准一致性模式(例如,
    gcc-std=c99-pedantic
    ),您将得到警告

    顺便说一句,如果您的实现支持,请不要使用
    %d
    打印
    sizeof
    的结果
    sizeof
    生成类型为
    size\t
    的结果,使用
    %zu
    ;如果不是,则需要使用强制转换将
    大小\u t
    值显式转换为可以打印的值。例如:

    printf("%lu\n", (unsigned long)sizeof &func);
    

    名称在C中没有类型。某些类型的名称表示具有类型的实体,如typedef名称、对象或函数。其他类型的名称表示没有类型的实体,如预处理器符号或
    goto
    标签。但其他类型的名称仅表示类型本身,即
    typedef
    名称

    函数名表示具有函数类型的实体。该函数类型包括返回类型和有关参数的信息(可能不完整)

    当函数用作值时,它们总是作为指向函数类型的指针进行操作。这样的函数不能在可移植的C程序中传递,但指向函数的指针可以传递

    从概念上讲,即使在像
    foo()
    这样的直接调用中,所发生的情况是
    foo
    ,一个表示函数的表达式,在求值时被隐式转换为指向函数值的指针。
    ()
    函数调用后缀操作符然后通过该指针调用函数

    有一条规则是,具有函数类型的表达式生成指针值,除非该表达式是
    &
    (的地址)或
    sizeof
    运算符的操作数。
    func
    &func
    仅为