c - void typedef 在 C 中如何工作

标签 c typedef

<分区>

我正在使用一个有意混淆的代码,其中包含一个我无法理解的奇怪类型定义。谁能解释以下 typedef 的含义:

typedef void (*p_t)(char* a1, char* a2, int a3);

后来主要使用如下:

int main(void) {
    p_t p = &some_function;
    p("foo", "bar", 42);
}

最佳答案

typedef void (*p_t)(char* a1, char* a2, int a3); 是指向接受参数 typedef 并返回 char* a1, char* a2, int a3(不返回)的函数的指针的 void


考虑一个函数声明(不涉及任何 typedef),例如:

void fn(char* a1, char* a2, int a3);

现在,假设您希望某个指针 p 指向此函数,那么像 p = fn 这样的赋值应该是有意义的。但是 p 的类型是什么?它将是一个指向函数的指针,但由于函数具有不同的签名(使函数的“类型”不同),您还需要指定它指向的函数的签名。在您的情况下,您需要一个指向接受三个参数的函数的指针:1.) 指向 char 的指针,2.) 另一个指向 char 的指针,以及 3.) int 的指针。此外,该函数返回 void 。所有这些都需要在 p 的类型中指定。所以你的 p 可能被声明(并随后分配)为

void (*p)(char* a1, char* a2, int a3);
p = fn;

可能看起来很奇怪的部分是 *(将 p 声明为指向某物的指针),它需要与 p 标识符放在括号中。看到像 (*p)(...) 这样的构造应该是一个快速提示,让您问自己是否正在查看指向函数的指针。如果您打算一遍又一遍地使用这样一个指向函数的指针,而不是必须一次又一次地键入所有内容(如果您决定更改函数签名,则可能会出现不一致的风险),制作 typedef 会很方便。在你的情况下,这是

typedef void (*p_t)(char* a1, char* a2, int a3);

请参阅 "Clockwise/Spiral Rule"


在你的例子中,你有

p_t p = &some_function;

这是声明一个类型为 p 的变量 p_t 。如上所述,这是一个指向接受三个参数并返回 void 的函数的指针。此行还使用值 p 初始化 &some_function 。显然 some_function 是在某处定义并接受这三个参数并返回 void 的函数的标识符。它初始化 p 以指向此函数,以便在下一行调用它:

p("foo", "bar", 42);

我很惊讶这不是写成

(*p)("foo", "bar", 42);

这取消引用 p ,它给出函数 some_function ,然后使用参数 "foo""bar"42 调用该函数。这很方便,因为您可以(如果需要)使 p 指向其他一些函数(具有相同的签名)。因此,关联函数可以是动态的。


值得一提的是,&中的p_t p = &some_function;并不是必须的。它不会伤害任何东西,但它不是必需的。函数指针的另一个奇怪之处在于,您可以根据需要多次引用和取消引用,它们的意思是一样的! (看 Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?)

关于c - void typedef 在 C 中如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49969739/

相关文章:

c++ - 在 Debian 上为您自己的应用程序添加 SNMP 支持的最佳方式

c - 使用 bazel 为具有模拟依赖项的 C 构建单元测试

c - 如何从 C for Windows 中的命令行读取 unicode 和数字参数?

c++ - 如何在两个类型定义 vector 上使用指针进行访问

无法将字符从指针复制到另一个指针(都分配了内存)

c - OpenGL - 如何从中心缩放对象?

c - 你如何阅读 C 声明?

swift - 协议(protocol)定义中是否可以将一种 Swift 类型别名限制为另一种类型别名?如果没有,我还能如何实现组件注册之类的功能?

c++ - 在运行时有条件地定义 3 个类中的哪一个将在其余 C++ 代码中使用

c++ - 重载 typedef 参数