typedef 如何用于函数指针

发布于 2025-01-07 05:01:47 字数 882 浏览 0 评论 0原文

我想我可能患有可怕的“意外程序员”病,至少在 typedef 和函数指针方面是这样。因此,我一直在尝试涉及这些的各种组合,以根据我得到的所有输出来分析结果。

但当我不断尝试不同的组合时,我现在没有分析结果,而是迷失在过程中。

我希望你们能帮我解决这个混乱的问题。

第一个代码示例

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

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

第二个代码示例

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

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

上面的两个代码示例是如何工作的,就好像“&”对函数名称没有影响

第三个代码示例

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();

我希望上述作业之一可以在这里工作,但是该死!我真的不明白函数指针(也许还有 typedef)。

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.

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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

GRAY°灰色天空 2025-01-14 05:01:47

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

类似地,当使用函数指针时,多重解引用不是问题:

#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)();
}

这可以在以下条件下干净地编译:

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

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

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.

嘴硬脾气大 2025-01-14 05:01:47

关于函数指针的事情是,它们是函数指针!:-) 这就是让第三个示例工作的方式:

#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;
}

就您是否使用 funcName 或 < code>&funcName,没关系(至少在 C 语言中)。 6.3.2.1 左值、数组和函数指示符 节指出:

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

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:

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".

浮生面具三千个 2025-01-14 05:01:47

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

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).

云朵有点甜 2025-01-14 05:01:47

与 C 一样,C++ 也有指向函数的指针:例如,void (*)() 是指向不带参数且不返回值的函数的指针。然而,C++ 还引入了对函数 void (&)() 的引用,并且两者之间存在隐式转换(尽管我不记得确切的规则)。

因此:

  • funcname 是对函数的引用
  • &funcname 是指向函数的指针

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

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).

Therefore:

  • funcname is a reference to function
  • &funcname is a pointer to function

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文