来自未初始化变量的 memcpy 是未定义的行为吗?

Is it undefined behaviour to memcpy from an uninitialized variable?

是否使用未初始化的变量作为 C 中 memcpy 未定义行为的 src

void foo(int *to)
{
  int from;
  memcpy(to, &from, sizeof(from));
}

(之前-没注意到地址from被传)。不,这不会导致未定义的行为,只是 from 具有不确定的值。只要您打算使用未初始化变量的值,程序就会有明确定义的行为。

(因为分配 space 而不初始化变量不是 UB 。)

这是关于复制操作的定义行为,除非 int 在您的系统中有陷阱表示。定义 int from 时在堆栈上分配了内存。 int 的内容是当时堆栈中该位置上发生的任何内容。因此,最终结果,被复制到 toint 的值未定义(不确定)。

其他答案引用了 C 标准,当未初始化变量的值为 "used" 时,会发生未定义的行为。如果您不使用该值,这显然不适用。 C11 标准未定义行为中还有另一个提及,而 copying/assigning 未初始化变量:

6.3.2.1p2

If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

这也不影响您的代码,因为 from 的地址在您调用 memcpy

时被占用

C11 标准的另一个相关部分是 6.2.6.1

Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined) Such a representation is called a trap representation.

一些非常老的处理器可能有一个 陷阱表示 用于 int 软件可见的奇偶校验位或非二进制补码架构中的 "negative zero" .例如,x86 处理器没有 int.

的陷阱表示

C 委员会对 defect report 451: instability of uninitialized automatic variables 的建议回应是:

The answer to question 3 is that library functions will exhibit undefined behavior when used on indeterminate values.

缺陷中的问题已寻求 memcpy 和 fwrite 的豁免,如果确实如此的话:

[...] The fact that one wants to be able to copy uninitialized padding bytes in structs using memcpy without undefined behavior is the reason that using the value of an uninitialized object is not undefined behavior. This seems to suggest that an fwrite of a struct with uninitialized padding bytes should not exhibit undefined behavior.

建议响应的这一部分似乎是针对未初始化填充的问题:

The committee also notes that padding bytes within structures are possibly a distinct form of "wobbly" representation.

我们可以看出 defect report 338: C99 seems to exclude indeterminate value from being an uninitialized register 这与过去的预期有些不同。除其他外,它说:

[...] I believe the intent of excluding type unsigned char from having trap representations was to allow it to be used to copy (via memcpy) arbitrary memory, in the case that memory might contain trap representations for some types.[...]

博客 post Reading indeterminate contents might as well be undefined 很好地介绍了在 C 语言中读取不确定值的演变过程,并对我上面提到的变化有了更多的了解。

值得注意的是这与 C++ 不同,其中 reading an indeterminate value from a narrow unsigned char is not undefined behavior and defect report 240 指出了这个区别:

The C committee is dealing with a similar issue in their DR338. According to this analysis, they plan to take almost the opposite approach to the one described above by augmenting the description of their version of the lvalue-to-rvalue conversion. The CWG did not consider that access to an unsigned char might still trap if it is allocated in a register and needs to reevaluate the proposed resolution in that light. See also issue 129.