typedef如何用于函数指针

时间:2021-10-22 00:22:32

I think I may be suffering from the dreaded "accidental programmer" disease, at least when it comes to typedefs and function pointers. So I've been experimenting with all kinds of combinations involving these to analyse the results based on all the output I get.

我想我可能患有可怕的“偶然程序员”疾病,至少在涉及typedef和函数指针时。所以我一直在试验各种涉及这些的组合,根据我得到的所有输出来分析结果。

But as I kept on trying different combinations, instead of analyzing the results I'm now just lost in process.

但是,当我继续尝试不同的组合,而不是分析结果,我现在只是在过程中丢失。

I'm hoping you guys will help me figure out this mess.

我希望你们能帮助我搞清楚这个烂摊子。

First code example

第一个代码示例

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print *pr;
pr = &do_something;
pr(); // Hello World

Second code example

第二个代码示例

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print *pr;
pr = do_something;
pr(); // Hello World

How do both the above code examples work, it's as if '&' has no effect on function name

上面的代码示例如何工作,好像'&'对函数名称没有影响

third code example

第三个代码示例

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print pr;
pr = do_something; // compile error
pr = &do_something; // compile error
pr();

I was hoping one of the above assignments to work here but damn! I really don't understand function pointers (and maybe typedef too).

我希望上面的任务之一可以在这里工作但该死的!我真的不懂函数指针(也可能是typedef)。

4 个解决方案

#1


19  

The address of a function name and the plain function name both mean the same thing, so & has no effect on a function name.

函数名称的地址和普通函数名称都是相同的,因此&对函数名称没有影响。

Similarly, when using function pointers, multiple dereferencing isn't a problem:

同样,使用函数指针时,多个解除引用不是问题:

#include <stdio.h>
typedef void print(void);
static void dosomething(void) { printf("Hello World\n"); }

int main(void)
{
    print *f1 = dosomething;
    print *f2 = &dosomething;
    f2();
    (f1)();
    (*f1)();
    (**f2)();
    (***f1)();
    (****f2)();
    (*****f1)();
}

That compiles cleanly under:

在以下情况下完全编译:

gcc -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -std=c99 xx.c -o xx

I would not claim that multiple stars is good style; it isn't. It is 'odd, and (yes, you may say it) perverse'. One is sufficient (and the one star is mainly for people like me who learned to program in C before the standard said "it is OK to call a function via a pointer without using the (*pointer_to_function)(arg1, arg2) notation; you can just write pointer_to_function(arg1, arg2) if you like"). Yes, it is weird. No, no other type (or class of types) exhibits the same behaviour, thank goodness.

我不会说多颗星是好的风格;事实并非如此。它是'奇怪的,(是的,你可能会说)反常'。一个就足够了(一个明星主要是像我这样的人,在标准之前学会用C编程说“可以通过指针调用函数而不使用(* pointer_to_function)(arg1,arg2)表示法;你如果你喜欢“),可以写出pointer_to_function(arg1,arg2)。是的,这很奇怪。不,没有其他类型(或类别类型)表现出相同的行为,谢天谢地。

#2


7  

The thing about function pointers is that they're function pointers! :-) This is how you get your third sample to work:

关于函数指针的事情是它们是函数指针! :-)这就是你的第三个样本的工作方式:

#include <stdio.h>
typedef void (*print)(void);
//            ^
void do_something (void) { printf("Hello World\n"); }
int main (void) {
    print pr;
    pr = do_something; // &do_something would also work.
    pr();
    return 0;
}

In terms of whether you use funcName or &funcName, it doesn't matter (in C at least). Section 6.3.2.1 Lvalues, arrays and function designators states:

无论您使用的是funcName还是&funcName,都无关紧要(至少在C中)。第6.3.2.1节Lvalues,数组和函数指示符指出:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator 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".

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

#3


3  

It turns out that, in C/C++, both funcname and &funcname will yield the address of funcname and can be assigned to a function pointer variable. This is actually just an oddity of how the syntax was designed for the language(s).

事实证明,在C / C ++中,funcname和&funcname都将产生funcname的地址,并且可以分配给函数指针变量。这实际上只是为语言设计语法的一个奇怪之处。

#4


3  

Like C, C++ has pointer to functions: void (*)() for example is a pointer to a function that takes no argument and returns no value. However, C++ has also introduced references to functions void (&)() and there are implicit conversions between the two (though I don't remember the rules exactly).

与C类似,C ++具有指向函数的指针:void(*)()例如是一个指向函数的指针,该函数不带参数且不返回任何值。但是,C ++还引入了函数void(&)()的引用,并且两者之间存在隐式转换(尽管我不完全记得规则)。

Therefore:

  • funcname is a reference to function
  • funcname是对函数的引用

  • &funcname is a pointer to function
  • &funcname是函数的指针

Note that taking the address (or a reference to) a function that is overloaded requires a static_cast to the exact type (to resolve the overload).

请注意,将地址(或引用)过载的函数需要static_cast到确切的类型(以解决重载)。

#1


19  

The address of a function name and the plain function name both mean the same thing, so & has no effect on a function name.

函数名称的地址和普通函数名称都是相同的,因此&对函数名称没有影响。

Similarly, when using function pointers, multiple dereferencing isn't a problem:

同样,使用函数指针时,多个解除引用不是问题:

#include <stdio.h>
typedef void print(void);
static void dosomething(void) { printf("Hello World\n"); }

int main(void)
{
    print *f1 = dosomething;
    print *f2 = &dosomething;
    f2();
    (f1)();
    (*f1)();
    (**f2)();
    (***f1)();
    (****f2)();
    (*****f1)();
}

That compiles cleanly under:

在以下情况下完全编译:

gcc -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -std=c99 xx.c -o xx

I would not claim that multiple stars is good style; it isn't. It is 'odd, and (yes, you may say it) perverse'. One is sufficient (and the one star is mainly for people like me who learned to program in C before the standard said "it is OK to call a function via a pointer without using the (*pointer_to_function)(arg1, arg2) notation; you can just write pointer_to_function(arg1, arg2) if you like"). Yes, it is weird. No, no other type (or class of types) exhibits the same behaviour, thank goodness.

我不会说多颗星是好的风格;事实并非如此。它是'奇怪的,(是的,你可能会说)反常'。一个就足够了(一个明星主要是像我这样的人,在标准之前学会用C编程说“可以通过指针调用函数而不使用(* pointer_to_function)(arg1,arg2)表示法;你如果你喜欢“),可以写出pointer_to_function(arg1,arg2)。是的,这很奇怪。不,没有其他类型(或类别类型)表现出相同的行为,谢天谢地。

#2


7  

The thing about function pointers is that they're function pointers! :-) This is how you get your third sample to work:

关于函数指针的事情是它们是函数指针! :-)这就是你的第三个样本的工作方式:

#include <stdio.h>
typedef void (*print)(void);
//            ^
void do_something (void) { printf("Hello World\n"); }
int main (void) {
    print pr;
    pr = do_something; // &do_something would also work.
    pr();
    return 0;
}

In terms of whether you use funcName or &funcName, it doesn't matter (in C at least). Section 6.3.2.1 Lvalues, arrays and function designators states:

无论您使用的是funcName还是&funcName,都无关紧要(至少在C中)。第6.3.2.1节Lvalues,数组和函数指示符指出:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator 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".

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

#3


3  

It turns out that, in C/C++, both funcname and &funcname will yield the address of funcname and can be assigned to a function pointer variable. This is actually just an oddity of how the syntax was designed for the language(s).

事实证明,在C / C ++中,funcname和&funcname都将产生funcname的地址,并且可以分配给函数指针变量。这实际上只是为语言设计语法的一个奇怪之处。

#4


3  

Like C, C++ has pointer to functions: void (*)() for example is a pointer to a function that takes no argument and returns no value. However, C++ has also introduced references to functions void (&)() and there are implicit conversions between the two (though I don't remember the rules exactly).

与C类似,C ++具有指向函数的指针:void(*)()例如是一个指向函数的指针,该函数不带参数且不返回任何值。但是,C ++还引入了函数void(&)()的引用,并且两者之间存在隐式转换(尽管我不完全记得规则)。

Therefore:

  • funcname is a reference to function
  • funcname是对函数的引用

  • &funcname is a pointer to function
  • &funcname是函数的指针

Note that taking the address (or a reference to) a function that is overloaded requires a static_cast to the exact type (to resolve the overload).

请注意,将地址(或引用)过载的函数需要static_cast到确切的类型(以解决重载)。