将memcpy用于具有常量成员的目标结构是否合法?

SOD*_*IMM 6 c struct initialization const

例如,以下功能是合法的:

struct two_int {
  const int a, b;
}

void copy_two(const two_int *src, two_int *dest) {
  memcpy(dest, src, sizeof(two_int));
}
Run Code Online (Sandbox Code Playgroud)

似乎至少某些类型的常量定义值的修改是不允许的,但我不清楚这是否合格.

如果答案是"是不是允许,在一般的",我也想知道什么地方的特殊情况下dest重新与分配的内存malloc(并因此还没有分配任何值),如:

two_int  s = {.a = 1, .b = 2};
two_int *d = malloc(sizeof(two_int));
copy_two(&s, d);
Run Code Online (Sandbox Code Playgroud)

更新:对于新malloc结构的情况,似乎后面的问题似乎得到了肯定的回答(没关系),但我认为原始的,更普遍的问题仍然存在.

sup*_*cat 0

memcpy仅当实际目标对象没有静态或自动持续时间时,用于此类目的的使用才会定义行为。

给出代码:

struct foo { double const x; };
void outsideFunction(struct foo *p);

double test(void)
{
  struct foo s1 = {0.12345678};
  outsideFunction(&s1);
  return 0.12345678;
}
Run Code Online (Sandbox Code Playgroud)

编译器有权优化该函数以:

double test(void)
{
  static struct foo const s1 = {0.12345678};
  outsideFunction(&s1);
  return s1.x;
}
Run Code Online (Sandbox Code Playgroud)

在许多处理器上,加载具有任意常量的 double 的唯一方法是从保存该常量的对象加载其值,在这种情况下,编译器可以方便地知道必须保存常量 0.12345678 的对象 (s1.x)。最终的结果是,用于memcpy写入的代码s1.x可能会破坏数字常量 0.12345678 的其他用途。俗话说:“变量不会;常量不会”。讨厌的东西。

对于分配持续时间的对象来说,这个问题不会存在,因为 memcpy 要求编译器“忘记”先前存储在目标存储中的所有内容,包括任何“有效类型”。静态和自动对象的声明类型独立于存储在其中的任何内容而存在,并且不能通过“memcpy”或任何其他方式擦除,但分配持续时间对象仅具有会被擦除的“有效类型”。