您好,我有以下设计,我想知道通常 C 编译器(gcc 或 clang)是否会尝试在编译时解析函数指针,还是会一直保留到运行时。
在测试.h中:
typedef struct array_ {
size_t size;
void *array;
size_t (*get_size)(struct array_ *);
} array_t;
static inline size_t
get_size (array_t *A) {
return A->get_size(A);
}
在测试.c中:
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
static size_t _get_size (array_t *A) {
return A->size;
}
int main(void)
{
array_t *A = malloc(sizeof(array_t));
A->size = 3;
A->array = (int[]){1,2,3};
A->get_size = _get_size;
printf("%llu\n", A->get_size(A));
printf("%llu\n", get_size(A));
return 0;
}
我的问题是——A->get_size(A) 会在编译时解析为 _get_size(A) 还是 A->size? A->get_size() 总是比 get_size(A) 更有效还是它们编译成几乎相同的东西?
我意识到我问的是编译器会做什么或不会做什么,这取决于编译器和其他因素(例如优化级别),但总的来说是否有答案,或者它是否仅取决于太多因素?
编辑:为清楚起见,我省略了错误检查。
编辑:“gcc -S”代码。我认为正在取消引用指针。
main:
.LFB4:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl $24, %edi
call malloc
movq %rax, -24(%rbp)
movq -24(%rbp), %rax
movq $3, (%rax)
movl $1, -16(%rbp)
movl $2, -12(%rbp)
movl $3, -8(%rbp)
movq -24(%rbp), %rax
leaq -16(%rbp), %rdx
movq %rdx, 8(%rax)
movq -24(%rbp), %rax
movq $_get_size, 16(%rax)
movq -24(%rbp), %rax
movq 16(%rax), %rax
movq -24(%rbp), %rdx
movq %rdx, %rdi
call *%rax
movq %rax, %rsi
movl $.LC0, %edi
movl $0, %eax
call printf
movq -24(%rbp), %rax
movq %rax, %rdi
call get_size
movq %rax, %rsi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
最佳答案
由于您只是在使用函数指针的上方一行分配了函数指针,因此像 gcc 和 clang 这样的优秀编译器应该足够聪明,可以在编译时解析它。但是,一旦您开始在不同文件中的不同函数之间传递指向该结构的指针,它们几乎肯定不会在编译时解析它。
如果您想如此详细地了解您的编译器,您应该开始查看反汇编 list 。
如果您想在示例代码中使用类似的语法并高效地编译它,C++ 是一种很好的语言。
关于编译时函数 ptr 取消引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27335308/