C 如何在双人床内存放两条短裤和一个浮球?

C 如何在双人床内存放两条短裤和一个浮球?,c,C,我碰巧有一个嵌入式程序,需要我做一些位操作来存储更多的信息 我有两条短裤和一个花车。我需要将它存储到一个双精度存储器(64位),然后在不损失精度的情况下从该双精度存储器中检索所有信息。我只能使用C99有效操作,甚至不能在双精度上进行位移位 short x = 4012; short y=1234; float s = 0.8; double store = 0; 不幸的是,我不知道如何处理这个问题 如果你把你的短裤和漂浮物放在一起,在连续的记忆中,它实际上是两条短裤和一个漂浮物。同样的内存占用

我碰巧有一个嵌入式程序,需要我做一些位操作来存储更多的信息

我有两条短裤和一个花车。我需要将它存储到一个双精度存储器(64位),然后在不损失精度的情况下从该双精度存储器中检索所有信息。我只能使用C99有效操作,甚至不能在双精度上进行位移位

short x = 4012; short y=1234; float s = 0.8;
double store = 0;

不幸的是,我不知道如何处理这个问题

如果你把你的短裤和漂浮物放在一起,在连续的记忆中,它实际上是两条短裤和一个漂浮物。同样的内存占用。但是,您不必修改位来访问和修改单个变量。也许,使用struct实际上会节省内存,因为在与short和float交互时,不需要中间变量放入CPU寄存器。此外,你会发现你的代码中有很多潜在的bug

如果你把你的短裤和漂浮物放在一起,在连续的记忆中,它实际上是两条短裤和一个漂浮物。同样的内存占用。但是,您不必修改位来访问和修改单个变量。也许,使用struct实际上会节省内存,因为在与short和float交互时,不需要中间变量放入CPU寄存器。此外,你会发现你的代码中有很多潜在的bug

使用工会:

union Foo {
  struct {
    short x;
    short y;
    float s;
  } ssf;
  double dbl;
};

int main() {
  union Foo v;
  v.ssf.x = 4012;
  v.ssf.y = 1234;
  v.ssf.s = 0.8f;

  // read a double
  double store = v.dbl;

  // set the double value
  v.dbl = store;

  // read the float back out
  printf("%f\n", v.ssf.s);

  return 0;
}
使用工会:

union Foo {
  struct {
    short x;
    short y;
    float s;
  } ssf;
  double dbl;
};

int main() {
  union Foo v;
  v.ssf.x = 4012;
  v.ssf.y = 1234;
  v.ssf.s = 0.8f;

  // read a double
  double store = v.dbl;

  // set the double value
  v.dbl = store;

  // read the float back out
  printf("%f\n", v.ssf.s);

  return 0;
}

作为对nemequ答案的补充,内部
结构可以是匿名的,以避免不必要的键入:

union Foo {
  struct {
    short a;
    short b;
    float c;
  };
  double d;
};

int main() {
   union Foo foo;
   foo.a = 12;
   foo.c = 2.3f;
}

作为对nemequ答案的补充,内部
结构可以是匿名的,以避免不必要的键入:

union Foo {
  struct {
    short a;
    short b;
    float c;
  };
  double d;
};

int main() {
   union Foo foo;
   foo.a = 12;
   foo.c = 2.3f;
}

这绝对是一个风格问题,但我通常会尽量避免工会中的匿名会员。额外的输入有助于明确哪些值是离散的;例如,对于您的版本,设置
foo.a
是否会保留
foo.b
,并不清楚,但是设置
foo.d
不会。为了使代码在阅读时更容易理解,我宁愿多键入几个字符。为了保持样式和可读性,清除联合的使用文档将有助于避免任何混淆,同时保留匿名结构的使用。文档很好,但它不能替代一个好的、毫不奇怪的API。API应该尽可能帮助人们避免错误,即使他们没有完整阅读文档。有时这意味着要更详细一些,有时选择好的名称,有时添加注释以帮助改进编译器警告。这肯定是一个风格问题,但我通常会尽量避免联合中的匿名成员。额外的输入有助于明确哪些值是离散的;例如,对于您的版本,设置
foo.a
是否会保留
foo.b
,并不清楚,但是设置
foo.d
不会。为了使代码在阅读时更容易理解,我宁愿多键入几个字符。为了保持样式和可读性,清除联合的使用文档将有助于避免任何混淆,同时保留匿名结构的使用。文档很好,但它不能替代一个好的、毫不奇怪的API。API应该尽可能帮助人们避免错误,即使他们没有完整阅读文档。有时这意味着更详细一些,有时选择好的名称,有时添加注释以帮助改进编译器警告。设置一个联合的成员(
v.ssf
及其成员)并读取另一个(
v.dbl
)会产生未定义的行为。读取已设置的相同成员是可以的。除非
double
具有陷阱表示,否则它应该是相当安全的,如果每个成员的大小相同,则从一个联合中提取double应该是安全的,使用该值在另一个联合中设置它,并为联合其他字段获取相同的值。您可以想象使用memcpy只设置double的必要位,但是如果存在陷阱表示,您也会遇到同样的问题。在实践中,唯一的担心是,结构将被填充或短,浮点分别不是16和32位。@彼得:C++禁止,但是。(IIRC,在如何允许它方面存在问题,但它尝试了。)也就是说,当双精度值变为NaN时,这很可能会给出错误的结果,甚至是发出NaN信号的陷阱。考虑到OP的限制,我认为不能对陷阱表示做任何事情。如果您想使用相同的内存来存储double和int,那么最终可能会出现问题值。至于NaN,可以安全地在NaN周围复制,并假设最终会得到一个稍微精确的副本,然后可以将其插入到联盟中,但我不确定C标准是否能保证这一点,或者只是在硬件中以另一种方式实现它是无意义的。设置联盟成员(
v.ssf
及其成员)而阅读另一个(
v.dbl
)会给出未定义的行为。读取已设置的相同成员是可以的。除非
double
具有陷阱表示,否则它应该是相当安全的,如果每个成员的大小相同,则从一个联合中提取double应该是安全的,使用该值在另一个联合中设置它,并为联合其他字段获取相同的值。您可以想象使用memcpy只设置double的必要位,但是如果存在陷阱表示,您也会遇到同样的问题。在实践中,唯一的担心是,结构将被填充或短,浮点分别不是16和32位。@彼得:C++禁止,但是。(IIRC,在如何允许它方面存在问题,但它尝试了。)也就是说,当双精度值变为NaN时,这很可能会给出错误的结果,甚至是发出NaN信号的陷阱。考虑到OP的限制,我认为不能对陷阱表示做任何事情。如果你想使用