这既是一个答案,也是一个问题。我意识到这个线程已经死了,但这正是我今晚正在研究的。
我做了一些探索,最接近我想要的东西(这与你想要的相似......我一直在使用图片并且不需要使用 C++,但我很好奇它是如何完成的) 是第一个代码示例:
#include <iostream>
using namespace std;
extern "C"
{
typedef struct stuff
{
int x;
double y;
} things;
}
int main()
{
things jmcd = { jmcd.x = 12, jmcd.y = 10.1234 };
cout << jmcd.x << " " << jmcd.y << endl;
return 0;
}
这与 C99 风格的指定初始化器外观非常相似,但需要注意的是我稍后会提到。(如果您希望结构体由其中任何一个编译,您可能会将其包装在 #ifdef __cplusplus 中。)我查看的第二个版本的代码是这样的:
#include <iostream>
using namespace std;
extern "C"
{
typedef struct stuff
{
int x;
double y;
} things;
}
int main()
{
things jmcd;
jmcd.x = 12;
jmcd.y = 10.1234;
cout << jmcd.x << " " << jmcd.y << endl;
return 0;
}
基本上,从反汇编来看,第一个示例似乎实际上更慢。我查看了汇编输出,嗯,我一定有点生疏了。也许有人可以给我一些见解。编译后的第一个 cpp 的程序集输出如下所示:
main:
.LFB957:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
movl %esp, %ebp
.cfi_offset 5, -8
.cfi_def_cfa_register 5
subl $24, %esp
movl $0, 12(%esp)
movl $0, 16(%esp)
movl $0, 20(%esp)
movl $12, 12(%esp)
movl 12(%esp), %eax
movl %eax, 12(%esp)
fldl .LC0
fstpl 16(%esp)
fldl 16(%esp)
fstpl 16(%esp)
movl 12(%esp), %eax
movl %eax, 4(%esp)
fildl 4(%esp)
fldl 16(%esp)
faddp %st, %st(1)
fnstcw 2(%esp)
movzwl 2(%esp), %eax
movb $12, %ah
movw %ax, (%esp)
fldcw (%esp)
fistpl 4(%esp)
fldcw 2(%esp)
movl 4(%esp), %eax
leave
ret
.cfi_endproc
第二个示例如下所示:
main:
.LFB957:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
movl %esp, %ebp
.cfi_offset 5, -8
.cfi_def_cfa_register 5
subl $24, %esp
movl $12, 12(%esp)
fldl .LC0
fstpl 16(%esp)
movl 12(%esp), %eax
movl %eax, 4(%esp)
fildl 4(%esp)
fldl 16(%esp)
faddp %st, %st(1)
fnstcw 2(%esp)
movzwl 2(%esp), %eax
movb $12, %ah
movw %ax, (%esp)
fldcw (%esp)
fistpl 4(%esp)
fldcw 2(%esp)
movl 4(%esp), %eax
leave
ret
.cfi_endproc
这两个都是用g++ -O0 -S main.cpp
命令生成的。显然,直观上效率较低的示例在指令数量方面生成了更有效的操作码。另一方面,在少数情况下,我可以想象这几条指令是至关重要的。(另一方面,我真的很难理解不是由人类编写的程序集,所以也许我遗漏了一些东西......)我认为这为詹姆斯提出的问题提供了一个解决方案,尽管很晚。接下来我应该测试的是 C99 中是否允许相同的初始化;如果可行,我认为它完全解决了詹姆斯的问题。
免责声明:我不知道这对于 g++ 以外的任何其他编译器是否有效或行为相似。