在符合 c ansi 标准的 scanf 中使用 malloc

Is using malloc within scanf compliant to c ansi standard

我想读取用户的输入并保存。我现在所拥有的确实有效,但我需要知道 scanf 在为输入分配内存之前首先分配变量 "length" 是否合法(遵循 ansi 标准 - c90), 或者如果它只是编译器的一个怪癖。

#include <stdio.h>
int main()
{
    char* text;
    int length = 0;
    scanf("%s%n", text = malloc(length+1), &length);

    printf("%s", text);

    return 0;
}  

不会如您所愿。

在您调用 malloc 时,length 的值仍然为 0,因此您只分配了一个字节。 length 直到 scanf returns 之后才更新。因此,任何非空字符串都将写入已分配缓冲区的边界,调用 undefined behavior.

虽然不完全相同,但您可以使用 getline,假设您 运行 在 POSIX 系统上比如Linux。此函数读取一行文本(包括换行符)并为该行分配 space。

char *text = NULL;
size_t n = 0;
ssite_t rval = getline(&text, &n, stdin);

if (rval == -1) {
    perror("getline failed");
} else {
    printf("%s", text);
}
free(text);

除了另一个答案中提到的滥用 scanf 的明显问题外,这也不遵循任何 C 标准:

#include <stdio.h>
...
text = malloc(length+1)

由于您没有在找到 malloc 的地方包含 stdlib.h,C90 将假定函数 malloc 具有 int malloc(int); 的形式,这当然是无稽之谈。

然后当您尝试将 int(malloc 的结果)分配给 char* 时,您违反了 C90 6.3.16.1 的约束,即简单赋值规则。

因此您的代码不允许干净地编译,但编译器必须给出诊断消息。

您可以通过升级到标准 ISO C 来避免此错误。

其他人很好地解释了问题

I want to read the input of a user and save it

要添加并实现 OP 的目标,可以使用类似的代码

int length = 255;
char* text = malloc(length+1);
if (text == NULL) {
  Handle_OOM();
} 
scanf("%255s%n", text, &length);

// Reallocate if length < 255 and/or 
if (length < 255) {
  char *t = realloc(text, length + 1);
  if (t) text = t;
} else {
  tbd(); // fail  when length == 255 as all the "word" is not certainly read.
}

如果过多的输入被认为是敌对的,以上将是一个简单的方法。