C语言中是定义结构体还是函数?

3

我正在尝试理解Linux中的KVM代码,遇到了这个:

    static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
[SVM_EXIT_READ_CR0]         = cr_interception,
[SVM_EXIT_READ_CR3]         = cr_interception,
[SVM_EXIT_READ_CR4]         = cr_interception,
[SVM_EXIT_READ_CR8]         = cr_interception,
[SVM_EXIT_CR0_SEL_WRITE]        = emulate_on_interception,
[SVM_EXIT_WRITE_CR0]            = cr_interception,
[SVM_EXIT_WRITE_CR3]            = cr_interception,
[SVM_EXIT_WRITE_CR4]            = cr_interception,
[SVM_EXIT_WRITE_CR8]            = cr8_write_interception,
[SVM_EXIT_READ_DR0]         = dr_interception,
[SVM_EXIT_READ_DR1]         = dr_interception,
[SVM_EXIT_READ_DR2]         = dr_interception,
[SVM_EXIT_READ_DR3]         = dr_interception,
[SVM_EXIT_READ_DR4]         = dr_interception,
[SVM_EXIT_READ_DR5]         = dr_interception,
[SVM_EXIT_READ_DR6]         = dr_interception,
[SVM_EXIT_READ_DR7]         = dr_interception,
[SVM_EXIT_WRITE_DR0]            = dr_interception,
[SVM_EXIT_WRITE_DR1]            = dr_interception,
[SVM_EXIT_WRITE_DR2]            = dr_interception,
[SVM_EXIT_WRITE_DR3]            = dr_interception,
[SVM_EXIT_WRITE_DR4]            = dr_interception,
[SVM_EXIT_WRITE_DR5]            = dr_interception,
[SVM_EXIT_WRITE_DR6]            = dr_interception,
[SVM_EXIT_WRITE_DR7]            = dr_interception,
[SVM_EXIT_EXCP_BASE + DB_VECTOR]    = db_interception,
[SVM_EXIT_EXCP_BASE + BP_VECTOR]    = bp_interception,
[SVM_EXIT_EXCP_BASE + UD_VECTOR]    = ud_interception,
[SVM_EXIT_EXCP_BASE + PF_VECTOR]    = pf_interception,
[SVM_EXIT_EXCP_BASE + NM_VECTOR]    = nm_interception,
[SVM_EXIT_EXCP_BASE + MC_VECTOR]    = mc_interception,
[SVM_EXIT_INTR]             = intr_interception,
[SVM_EXIT_NMI]              = nmi_interception,
[SVM_EXIT_SMI]              = nop_on_interception,
[SVM_EXIT_INIT]             = nop_on_interception,
[SVM_EXIT_VINTR]            = interrupt_window_interception,
[SVM_EXIT_RDPMC]            = rdpmc_interception,
[SVM_EXIT_CPUID]            = cpuid_interception,
[SVM_EXIT_IRET]                         = iret_interception,
[SVM_EXIT_INVD]                         = emulate_on_interception,
[SVM_EXIT_PAUSE]            = pause_interception,
[SVM_EXIT_HLT]              = halt_interception,
[SVM_EXIT_INVLPG]           = invlpg_interception,
[SVM_EXIT_INVLPGA]          = invlpga_interception,
[SVM_EXIT_IOIO]             = io_interception,
[SVM_EXIT_MSR]              = msr_interception,
[SVM_EXIT_TASK_SWITCH]          = task_switch_interception,
[SVM_EXIT_SHUTDOWN]         = shutdown_interception,
[SVM_EXIT_VMRUN]            = vmrun_interception,
[SVM_EXIT_VMMCALL]          = vmmcall_interception,
[SVM_EXIT_VMLOAD]           = vmload_interception,
[SVM_EXIT_VMSAVE]           = vmsave_interception,
[SVM_EXIT_STGI]             = stgi_interception,
[SVM_EXIT_CLGI]             = clgi_interception,
[SVM_EXIT_SKINIT]           = skinit_interception,
[SVM_EXIT_WBINVD]                       = emulate_on_interception,
[SVM_EXIT_MONITOR]          = invalid_op_interception,
[SVM_EXIT_MWAIT]            = invalid_op_interception,
[SVM_EXIT_XSETBV]           = xsetbv_interception,
[SVM_EXIT_NPF]              = pf_interception,

};

我精通C语言,但从未在任何地方看到过这种写法,真的很困惑这是一个函数还是一个结构体声明或其他。非常感谢任何帮助。


const 关键字的存在使得这是一个 C++ 问题,而不是 C 的构造。 - SGM1
但是,这是Linux内核代码的一部分,并且作为文件vmx.c存在于linux/arch/x86/kvm/中。 - Minerva
2
@SGM1:当然不是!const 是有效的 C 代码,而指定初始化器则无效。此外,在 Linux 内核树中不允许出现任何 C++ 语言。 - Ben Voigt
@SGM1,“const”自1999年起就在C语言中存在。 - Jens Gustedt
@BenVoigt和JensGustedt。好的,我之前被告知C语言中没有这个功能,但现在我知道了,谢谢。 - SGM1
const是C89中的一部分,它是有史以来第一个C语言标准。 - M.M
2个回答

6

这是一个函数指针数组。

使用指定的初始化器进行初始化。

编辑:声明可以解读为--

svm_exit_handlers声明为静态的常量指向带有指向struct vcpu_svm的指针并返回int的函数数组。

(您可能会发现http://www.cdecl.org对于解析困难的C声明有所帮助。)

更通俗易懂的说法是,这是一个函数指针数组。指针指向的函数形式为int foo(struct vcpu_svm *svm)

编辑:指定的初始化程序可能会有些令人困惑。请参见http://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html


谢谢。我能理解vm_exit_handlers[]部分,但是对于“(*const svm_exit_handlers[])(struct vcpu_svm *svm)”的存在感到困惑。另外,您能否进一步详细说明声明? - Minerva
分解:typedef int FUNC_TYPE(struct vcpu_svm *); static FUNCTYPE *const svm_exit_handlers[] = { ... }; const 表示数组中的值不能被更改(与指向的函数不同,这是没有意义的)。static 表示 svm_exit_handlers 只在当前单元内可见(并非指向的函数是静态的)。 - M.M
我不理解花括号中方括号的存在,感谢提供链接,下一个项目会使用它们XD,谢谢,我在SO上正在寻找这个。 - SGM1
@SGM1 -- 大括号 {} 内的方括号是数组的指定初始化器。这意味着,例如 svm_exit_handlers[SVM_EXIT_READ_CR0] = cr_interception - cklin
我只是在5分钟内添加了一条评论,谢谢。 - SGM1

0

这是一个函数指针数组的初始化,它接受一个 (struct vcpu_svm *svm) 并返回一个 int。


“takes (struct vcpu_svm *svm)” 的意思是什么?我对其中的 struct 不太理解。谢谢。 - Minerva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接