我既是回答者也是提问者。我知道这个帖子已经过期了,但今晚我正好在研究这个问题。
我查了一些资料,最接近我想要的(与你所需相似...我一直在处理图片,没有使用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++之外的其他编译器。