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

问题描述 投票:3回答:3

我想阅读用户的输入并保存。我现在有什么工作,但我需要知道它是否合法(遵循ansi标准 - c90)scanf在为输入分配内存之前首先分配变量“length”,或者它只是编译器的一个怪癖。

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

    printf("%s", text);

    return 0;
}  
c c89
3个回答
8
投票

这不会像你期望的那样工作。

在你调用malloc的时候,length的值仍为0,所以你只需要分配一个字节。 length直到scanf返回后才更新。因此,任何非空字符串都将写入已分配缓冲区的边界,并调用undefined behavior

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

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
投票

除了在另一个答案中解决了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来避免此错误。


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.
}

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

© www.soinside.com 2019 - 2024. All rights reserved.