在 C 中,作为参数传递时,`&function` 和 `function` 有啥区别?
Posted
技术标签:
【中文标题】在 C 中,作为参数传递时,`&function` 和 `function` 有啥区别?【英文标题】:In C, what is the difference between `&function` and `function` when passed as arguments?在 C 中,作为参数传递时,`&function` 和 `function` 有什么区别? 【发布时间】:2011-09-11 17:06:03 【问题描述】:例如:
#include <stdio.h>
typedef void (* proto_1)();
typedef void proto_2();
void my_function(int j)
printf("hello from function. I got %d.\n",j);
void call_arg_1(proto_1 arg)
arg(5);
void call_arg_2(proto_2 arg)
arg(5);
void main()
call_arg_1(&my_function);
call_arg_1(my_function);
call_arg_2(&my_function);
call_arg_2(my_function);
运行这个我得到以下信息:
> tcc -run try.c
hello from function. I got 5.
hello from function. I got 5.
hello from function. I got 5.
hello from function. I got 5.
我的两个问题是:
使用(* proto)
定义的函数原型与未定义的函数原型有什么区别?
使用引用运算符 (&
) 和不使用引用运算符调用函数有什么区别?
【问题讨论】:
我认为没有区别。没有发布作为答案,因为我不太确定。 Function pointers in C - address operator "unnecessary" 的可能重复项 【参考方案1】:没有区别。有关证据,请参阅C99 specification(第 6.7.5.3.8 节)。
“将参数声明为‘函数返回类型’”应调整为“指针指向” 函数返回类型'',如 6.3.2.1。"
【讨论】:
感谢尼克的参考! (顺便说一下,这是第 6.7.**5**.3.8 节。)所以它本质上是一种语言特殊情况? @brice - 谢谢我编辑。是的,一个特例。函数指针 one 对于与语言的其余部分保持一致更有意义,但我猜他们添加了另一种情况以提高可读性 由此得出的结论是,您可以显式取消引用函数名称或函数指针以及任意次数(零、一次或多次)并始终获得相同的结果:***.com/questions/5834520/c-function-pointers/… 这只是事实的一半:6.7.5.3.8 只关心类型声明;函数指示符到函数指针的隐式转换在第 6.3.2.1 节中介绍【参考方案2】:&function
和 function
作为参数传递时没有区别
但是你的 typedef 是有区别的。我不知道官方的解释,即到底有什么区别,但据我记得
typedef void (*name1)(void);
和
typedef void(name2)(void);
不同:
name1 是一个指向函数的指针,它不带参数并且不返回任何内容
name2 是一个不带参数且不返回任何内容的函数
你可以通过编译来测试:
typedef void (*pointer)(void);
typedef void (function)(void);
void foo(void)
int main()
pointer p;
function f;
p = foo; //compiles
p();
f = foo; //does not compile
f();
再一次,我不是解释这种行为的确切原因的合适人选,但我相信如果你看一下标准,你会在某处找到解释
【讨论】:
我猜你已经能感觉到这个来了:...当作为争论传递时 - 那么有什么区别呢? :-) 呵呵 :) 不确定,但据我所知完全一样。为什么它们都存在?我不知道。我认为它就像 int & const r;和 int &r; c++的 感谢您对 typedef 的澄清。这是有道理的,并且遵循通常的语义。【参考方案3】:&function 和 function 之间没有区别——它们都是地址。你可以通过打印它们来看到这一点:
function bar();
....
printf("addr bar is 0x%d\n", &bar);
printf("bar is 0x%d\n", bar);
【讨论】:
您的答案是正确的,但是“您可以通过...看到这个”是错误的。对于一个数组,array
和&array
并不完全一样(它们有非常 不同的类型!)但是用printf
打印它们的地址会显示相同的东西(假设你正确使用@ 987654325@ 而不是 %d
并转换为 void *
)。顺便说一句,没有办法用 printf
打印函数指针,因为 C 完全没有从函数指针类型到 void *
或任何整数类型的任何转换。
“无法打印函数指针”的说法是不正确的。您可以运行我在上面粘贴的代码(我这样做了)。
该代码通过将不匹配的类型传递给printf
来调用未定义的行为。如果它达到了你的预期,那就意味着你运气不好,即你的代码中的错误没有被发现。
顺便说一句,在十进制数字前打印0x
是相当不正当的... :-)
另外,虽然在 C 语言中数组和 &array 确实不同,但它们编译为相同的值:地址。我认为本着 OP 问题的精神,指出这一点是有帮助的。【参考方案4】:
区别只是风格上的。使用函数指针时,您有相同的场景:
void func (void);
...
void(*func_ptr)(void) = func;
func_ptr(); // call func
(*func_ptr)(); // call func
printf("%d\n", ptr);
printf("%d\n", *ptr);
有些人说更喜欢 (*func_ptr)() 语法,以明确函数调用是通过函数指针完成的。其他人认为带 * 的样式更清晰。
像往常一样,可能没有科学研究证明任何一种形式都比另一种更好,所以只需选择一种风格并坚持下去。
【讨论】:
以上是关于在 C 中,作为参数传递时,`&function` 和 `function` 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章