在标准 C 中从头开始实现 memcpy 在技术上是不可能的吗?

2023-12-23

霍华德朱writes https://twitter.com/hyc_symas/status/1088187814477553678:

在最新的 C 规范中,不可能编写 malloc 或 memcpy 的“合法”实现。

这是正确的吗?我的印象是,在过去,该标准的意图(至少)是这样的东西会起作用:

void * memcpy(void * restrict destination, const void * restrict source, size_t nbytes)
{
    size_t i;
    unsigned char *dst = (unsigned char *) destination;
    const unsigned char *src = (const unsigned char *) source;

    for (i = 0; i < nbytes; i++)
        dst[i] = src[i];
    return destination;
}

这里违反了最新 C 标准中的哪些规则?或者,规范的哪一部分memcpy这段代码没有正确实现?


For the mallocfunction,第 6.5 §6 段明确指出不可能编写一致且可移植的 C 实现:

The effective type of an object for an access to its stored value is the declared type of the object, if any(87)...

(非规范性)注释 87 说:

分配的对象没有声明类型。

声明没有声明类型的对象的唯一方法是...通过返回此类对象所需的分配函数!所以在分配函数中,你必须有某物标准不允许设置没有声明类型的内存区域。

在常见的实现中,标准库malloc和free确实是用C实现的,但是系统知道它并假设内部已经提供了字符数组malloc只是没有声明类型。句号。

但同一段的其余部分解释说,编写一个没有真正的问题memcpy实施(强调我的):

...如果通过一个值存储到一个没有声明类型的对象中 左值的类型不是字符类型,则左值的类型变为 该访问和不修改的后续访问的对象的有效类型 存储的值。如果使用以下方式将值复制到没有声明类型的对象中 memcpy 或 memmove,或者被复制为字符类型的数组,则有效类型 该访问以及不修改对象的后续访问的已修改对象的 value 是从中复制值的对象的有效类型(如果有)。为了 对没有声明类型的对象的所有其他访问,该对象的有效类型是 只是用于访问的左值的类型。

如果您将对象复制为字符类型数组(这是严格别名规则允许的特殊访问),那么实现就没有问题memcpy,并且您的代码是可能且有效的实现。

恕我直言,霍华德朱的咆哮是关于那个古老的好东西memcpy用法,不再有效(假设sizeof(float) == sizeof(int)):

float f = 1.0;
int i;
memcpy(&i, &f, sizeof(int));         // valid: copy at byte level, but the value of i is undefined
print("Repr of %f is %x\n", i, i);   // UB: i cannot be accessed as a float
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在标准 C 中从头开始实现 memcpy 在技术上是不可能的吗? 的相关文章

随机推荐