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

时间:2017-02-11 21:00:48

标签: 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));
}

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

如果答案是“一般情况下允许”,我也想知道destmalloc新分配的内存的特殊情况({1}}(因此尚未被赋予任何价值),例如:

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

更新:对于新malloc'd结构的情况,似乎后一个问题似乎得到肯定(可以)回答,但是原始的,更一般的问题我认为仍然有效。

1 个答案:

答案 0 :(得分: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;
}

编译器有权优化函数:

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

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

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