我正在尝试使用typedefs来理解函数声明。
这段代码在C++中有什么作用?
typedef void fcn_t(void);
typedef void (*ptr_t)(void);
fcn_t f;
fcn_t *pf;
ptr_t pf2;
在我的理解中:
fcn_t
是函数的类型,因此带有f
的行是函数声明(不是定义),我以后可以像void f(void) { blabla(); bleble(); }
一样定义它,就像我声明void f(void);
而不是fcn_t f;
一样;fcn_t *
是函数指针的类型,带有pf
的行是指针变量定义,pf
是默认初始化的(假设代码摘录来自全局范围);fcn_t*
和ptr_t
之间没有区别,因此我所说的关于pf
的一切都适用于pf2
。
我做对了吗?如果我将它们标记为extern
,这三个声明中的任何一个的含义会改变吗?如果代码编译为 C 而不是 C++,会发生什么变化?
是的,你在这三个方面都是对的。 如果您将它们标记为extern
,唯一会更改的是函数指针。 默认情况下,函数声明extern
C++。
尝试编译以下程序
template <typename...>
struct WhichType;
typedef void fcn_t(void);
typedef void (*ptr_t)(void);
// constexpr auto one = WhichType<fcn_t>{};
// constexpr auto two = WhichType<fcn_t*>{};
// constexpr auto three = WhichType<ptr_t>{};
fcn_t f;
void f() {}
int main() {
f();
}
取消注释行可能会给您带来编译器错误,告诉您实例的类型WhichType
,因此它应该向您显示您询问的所有三件事的确切类型。 这是我从斯科特·迈耶斯(Scott Meyers)的《有效的现代C++》(Effective Modern )一书中学到的一个技巧。
要测试声明是否为 extern,请编写两个简单的实现文件,其中一个包含变量的定义
主.cpp
template <typename...>
struct WhichType;
typedef void fcn_t(void);
typedef void (*ptr_t)(void);
fcn_t f;
int main() {
f();
}
定义.cpp
void f() {}
然后编译、链接和运行definition.cpp
和main.cpp
(通过g++ -std=c++14 definition.cpp main.cpp
然后./a.out
)。 如果声明不是 extern,则编译将失败并显示未定义的符号错误。
以下是这些typedef
的简单说明
#include <stdio.h>
typedef void fcn_t(void);
typedef void (*ptr_t)(void);
fcn_t f;
fcn_t *pf;
ptr_t pf2;
void
f(void)
{
printf("I am voidn");
}
void
vSayHi(void)
{
printf( "Hin" );
}
int
main(void)
{
pf2 = vSayHi;
pf2();
pf = vSayHi;
pf();
f();
return 0;
}
输出:
Hi
Hi
I am void