最近我一直在工作的一些嵌入式设备,在这里我们有一些结构和需要在编译时被初始化,使我们能够保持在闪存或ROM某些事情不需要修改工会,和节省一点闪存或SRAM在位性能为代价的。目前,该代码编译为有效C99,但没有这种调整它用来编译为C ++代码,以及,被编译的方式也将是巨大的支持的事情。其中之一是防止这种关键的事情是,我们正在使用C99指定的初始不C ++的C子集范围内工作。我没有太大的C ++的buff,所以我不知道有什么简单的方法,有可能是实现这一目标用C ++兼容C或C ++中仍然允许初始化在编译的时候,这样的结构和联合不必在SRAM程序启动后初始化。

请注意的一个附加点:用于指定初始化的使用的一个关键原因是作为initalizing NOT一个联合的第一个成员。此外,与标准的C ++或ANSI C粘着是为了保持与其它编译器的相容性的加(我知道有关GNU扩展,提供类似指定的初始值,而不C99)。

有帮助吗?

解决方案

我不知道你能做到这一点的C ++。对于那些需要使用指定的初始化程序初始化的东西,你可以编译为C99,e.g一个.c文件把这些分开:

// In common header file
typedef union my_union
{
    int i;
    float f;
} my_union;

extern const my_union g_var;

// In file compiled as C99
const my_union g_var = { .f = 3.14159f };

// Now any file that #include's the header can access g_var, and it will be
// properly initialized at load time

其他提示

大厦成业的回答,并用3年的时间效益,C ++ 11现在可以保证编译时初始化:

union Bar
{
    constexpr Bar(int a) : a_(a) {}
    constexpr Bar(float b) : b_(b) {}
    int a_;
    float b_;
};

extern constexpr Bar bar1(1);
extern constexpr Bar bar2(1.234f);

大会:

    .globl  _bar1                   ## @bar1
    .p2align    2
_bar1:
    .long   1                       ## 0x1

    .globl  _bar2                   ## @bar2
    .p2align    2
_bar2:
    .long   1067316150              ## float 1.23399997
#ifdef __cplusplus
struct Foo
{
    Foo(int a, int b) : a(a), b(b) {}
    int a;
    int b;
};

union Bar
{
    Bar(int a) : a(a) {}
    Bar(float b) : b(b) {}
    int a;
    float b;
};

static Foo foo(1,2);
static Bar bar1(1);
static Bar bar2(1.234f);
#else 
 /* C99 stuff */
#endif // __cplusplus

在C ++联合可以具有构造太。可能这是你想要的吗?

这是排序两者的答案和问题。我知道这个线程是死的,但它正是我一直在寻找到今晚。

我做了一些闲逛,我可以得到我想要的东西(这类似于你想要什么最接近......我一直在与图片,并没有必要使用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;如果这样的作品,我认为它完全解决了詹姆斯的问题。

声明:我不知道这是否正常工作或行为类似于比克++以外的任何其他的编译器

干井报告:

鉴于

struct S {
  int mA;
  int mB;
  S() {}
  S(int b} : mB(b) {} // a ctor that does partial initialization
};

我试图从S,其中S1的内联默认构造函数调用S(int)和通过硬编码的值导出S1 ...

struct S1 {
  S1() : S(22) {}
} s1;

...然后用gcc 4.0.1 -O2 -S编译。希望是优化器会看到s1.mB必然是22,并在编译时赋值,但是从汇编...

    movl    $22, 4+_s1-"L00000000002$pb"(%ebx)

...它看起来像所生成的代码执行初始化在运行时之前主。即使工作过,这决不会是编译为C99和必须推导你想初始化每个对象的类的杂牌;所以,不用麻烦。

下面的代码编译而不与克++问题:

#include <iostream>

struct foo
{
  int a;
  int b;
  int c;
};

union bar
{
  int a;
  float b;
  long c;
};

static foo s_foo1 = {1,2,3};
static foo s_foo2 = {1,2};
static bar s_bar1 = {42L};
static bar s_bar2 = {1078523331}; // 3.14 in float


int main(int, char**)
{
  std::cout << s_foo1.a << ", " <<
               s_foo1.b << ", " <<
               s_foo1.c << std::endl;

  std::cout << s_foo2.a << ", " <<
               s_foo2.b << ", " <<
               s_foo2.c << std::endl;

  std::cout << s_bar1.a << ", " <<
               s_bar1.b << ", " <<
               s_bar1.c << std::endl;

  std::cout << s_bar2.a << ", " <<
               s_bar2.b << ", " <<
               s_bar2.c << std::endl;

  return 0;
}

下面是结果:

$ g++ -o ./test ./test.cpp
$ ./test
1, 2, 3
1, 2, 0
42, 5.88545e-44, 42
1078523331, 3.14, 1078523331

与C ++初始化的唯一事情是,需要初始化该结构的所有元件或其余部分将用零来初始化。你不能挑选。但是,这仍然应该是您的使用情况确定。

  

一音符的附加点:一个关键原因指定初始化使用作为initalizing NOT一个联合的第一个部件

有关你需要使用在我通过提供等效int值设置“浮动”件的例子中示出的“解决方法”。这是一个黑客位,但如果它解决您的问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top