为什么 malloc 使用零大小?

Why does malloc work with zero size?

这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{

   char* p;
   p = (char*)malloc(0);
   scanf("%s", p);
   printf("%s", p);
   free(p);
}

有人可以向我解释为什么我通过终端输入的每个词都会打印给用户吗?我有 malloc(0)。当我尝试 scanf 时不应该给我一个 segmentation fault 吗?

编辑

为什么这会给我一个编译错误:

p = malloc(sizeof(char) * 2)

当我尽量避免(void*)

error: cannot initialize a variable of type 'char *' with an rvalue of type 'void *'

opengroup-

If the size of the space requested is 0, the behavior is implementation-defined: the value returned shall be either a null pointer or a unique pointer.

malloc(0) 没有分配任何内容。因此,当您尝试使用 scanf 获取输入时,您会调用 undefined behaviour

Isn't supposed when i try to scanf to give me a segmentation fault?

不,当你有 UB 时就没有必要了。也许你没有那么幸运得到分段错误并获得所需的输出(这可能会混淆)。

malloc 的 C 标准明确规定:

If the size of the space requested is 0, the behavior is implementation-defined: the value returned shall be either a null pointer or a unique pointer.

对于 malloc 中的 return 值:

If size is 0, either a null pointer or a unique pointer that can be successfully passed to free() shall be returned. Otherwise, it shall return a null pointer and set errno to indicate the error.

关于调用 scanf 的分段错误,这纯粹是基于环境的实现和 运行 时间行为,只是运气而不是任何东西,下一次是 运行,它 可能 因分段错误而崩溃。

C 标准 9899:2011 7.22.3 指出:

If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.

意味着从 malloc returned 的是实现定义的行为。您必须阅读特定的编译器文档以了解它在您的情况下的作用:return 空指针或指向 0 字节数据(可能是随机垃圾位置)的非零指针。

在任何一种情况下,returned 指针都没有指向有效的内存位置。因此,如果您尝试写入它,您将调用未定义的行为。这意味着任何事情都可能发生:程序可能会崩溃并烧毁,或者它看起来可以正常工作并在一个月后崩溃,或者其他任何事情。

Why this gives me a compilation error: p = malloc(sizeof(char) * 2)

因为您正在尝试使用 C++ 编译器编译 C 代码。不要那样做。某些 C++ 编译器有一个选项,您可以将其设置为使用 C 编译器进行编译。


关于 C 标准中不一致的附注:

标准附件 J 实际上将上述行为列为未指定的行为。我怀疑这一定是附件 J 中的一个错误,因为上面引用的规范文本明确指出这是实现定义的。 7.22.3 是规范性的,Annex J 是信息性的,所以我会忽略 Annex J。