Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c中的函数指针(地址和引用运算符对函数的影响)_C_Types_Function Pointers - Fatal编程技术网

c中的函数指针(地址和引用运算符对函数的影响)

c中的函数指针(地址和引用运算符对函数的影响),c,types,function-pointers,C,Types,Function Pointers,可能重复: 我正在阅读C中的函数指针。我尝试了以下程序: #include <stdio.h> int foo(void) { printf("At foo."); return 0; } int main (void) { printf("%p\t%p\t%p\n", &foo, foo, *foo); return 0; } 在一维数组中,标识符和标识符指向相同的值,但值的性质不同。一种类型为datatype*,另一种类型为指向一维

可能重复:

我正在阅读C中的函数指针。我尝试了以下程序:

#include <stdio.h>

int foo(void)
{
    printf("At foo.");
    return 0;
}

int main (void)
{
    printf("%p\t%p\t%p\n", &foo, foo, *foo);
    return 0;
}

在一维数组中,
标识符
标识符
指向相同的值,但值的性质不同。一种类型为
datatype*
,另一种类型为指向一维数组的指针。类似地,对于函数,
foo
&foo
是相同的。但是关于
*foo
,以及
&foo,foo,*foo
的性质是什么?

一个普通的
foo
已经是一个函数指针了:

6.3.2.1-4

函数指示符是具有函数类型的表达式。 除非它是sizeof运算符或一元数的操作数 &运算符,类型为“”函数返回的函数指示符 类型“”已转换为具有指向的类型“”指针的表达式 函数返回类型“”

您可以使用
&
获取函数的地址,这将生成指向函数…的
指针:

6.5.3.1-1-3

一元运算符和运算符的操作数应为函数 指示器。。。一元&运算符生成其操作数的地址。 如果操作数的类型为“类型”, 结果的类型为“指向类型的指针”

将间接运算符应用于函数指示符是合法的

6.5.3.2-3

一元*运算符表示间接如果操作数指向 函数,结果是函数指示符

tldr:

好了。他们都做同样的事情


编辑 C语言中的“函数类型”是什么

快点!达到标准

6.2.5-1

类型被划分为对象类型(描述 对象)和函数类型(描述函数的类型)

6.2.5-20

函数类型描述具有特定返回类型的函数。A. 函数类型由其返回类型和 其参数的数量和类型。函数类型被称为 从其返回类型派生,如果其返回类型为T,则 函数类型有时称为“返回T的函数”。这个 调用从返回类型构造函数类型 “函数类型派生”


在C/C++中,函数只能以两种方式使用:您可以获取它的地址,也可以调用它。你不能用它做任何其他事情

所以,
foo
本身就是一个函数。C++具有标准转换<代码> 4.3函数,用于指针转换< /代码>。这意味着
foo
将自动转换为
&foo
。符号
&&&&foo
会导致语法错误

<> > C++ >代码> 5.3.1.1元运算符< /Cord>中有一个措辞,允许函数本身的结果去引用函数指针。这意味着不允许有多个
*
。尽管如此,它们至少在MSVC和GCC中工作。这可能是因为编译器在解引用后立即将
函数应用于指针转换
,然后再处理下一个操作

我看不出允许多个
*
和不允许多个
&
具有函数的理由。出于某种原因,
*
&
操作实现了不同的逻辑


您可以尝试将
foo
转换为
char*
并取消引用此指针。它将包含机器代码的字节。这些字节的长度未知。此地址的读/写保护也未知。许多CPU架构允许设置执行位而不设置读写位。因此,您可以调用函数,但尝试读取此地址可能会导致崩溃。

什么是“函数类型”,它如何通过间接方式反映返回函数的地址?我发现理解规范中使用的术语很复杂。函数指示符指用于标识函数的标签?(在本例中为foo)@ram,如果您觉得很难,那么在深入研究标准的吹毛求疵问题之前,您应该编写更多的程序。例如,编写有用的东西,而不是打印
foo
&foo
*foo
@cnicutar:当我阅读函数指针时,我发现隐式和显式地调用函数。也就是说(*fnptr)()和fnptr()都将在“fnptr”指向某个函数的地方工作。对于直觉,参考运算符对函数没有影响。所以我开始做更多的实验,这个问题是它的副产品。我很好奇。我的观点是,当人们多管闲事时,你应该鼓励他们,因为这会让他们知道新的事情。无论如何,谢谢你的回答,因为它解决了我的一些问题。@ram你是对的,但你也应该准备好阅读规范。你可能还对yes,:D感兴趣,[为了好玩,试试(************foo)()]@Kobelev,我已经读到函数标识符在几乎所有情况下都会自动衰减为函数指针,除了使用sizeof运算符或引用运算符。因此,因为&foo已经是一个l值,所以不能再次对其应用引用运算符&&foo导致错误。此外,正如您所提到的“在处理下一个操作之前,编译器在解引用之后立即应用函数到指针转换”,因此****foo工作正常。关于地址,我假设它是CPU执行例程时跳转到的地址。你知道,老实说,我看不出有什么深层次的逻辑。对我来说,这更多的是一组随机决策,由不同的编译器以相同的方式模拟。我们可以用函数做的事情不多。我倾向于接受这种情况,而不试图进行逻辑解释
0040138C    0040138C    0040138C