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

时间:2019-01-29 13:07:05

标签: c c89

我想读取用户的输入并保存。我现在所做的工作正常,但是我需要知道scanf的合法性(遵循ansi标准-c90)是否首先为变量“ length”分配变量,然后再为输入分配内存, 或仅仅是编译器的古怪之处。

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

    printf("%s", text);

    return 0;
}  

3 个答案:

答案 0 :(得分:8)

这将不能正常工作。

在调用malloc时,length的值仍为0,因此您只分配了一个字节。在length返回之前,scanf不会更新。因此,任何非空字符串都将写出已分配缓冲区的边界,并调用undefined behavior

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

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);

答案 1 :(得分:1)

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

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

由于您没有在找到stdlib.h的地方包含malloc,因此C90将假定函数malloc的形式为int malloc(int);,这当然是胡说八道。

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

因此,不允许您的代码进行干净地编译,但是编译器必须提供诊断消息。

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

答案 2 :(得分:1)

问题得到别人的很好解释

  

我想读取用户的输入并保存

要添加并实现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.
}

如果认为过多的投入是敌对的,上述方法将是一种简单的方法。