c - 为什么 `gets_s()` 仍然没有在 GCC (9.3.0) 中实现?

标签 c gcc c11 gets

我知道 fgets() 是一个更常见和广泛使用的字符串输入选项,但 C11 已经存在 9 年了。为什么 gets_s() 仍然没有工作?

即使我添加了 -std=c11,它仍然不起作用,即使 gets_s() 应该在 stdio.h 中>.

最佳答案

因为它是可选的。而 gcc 背后的人似乎认为包含它是个坏主意。我不知道他们是怎么推理的,但是在 C 标准中可以找到提示:

Recommended practice

The fgets function allows properly-written programs to safely process input lines too long to store in the result array. In general this requires that callers of fgets pay attention to the presence or absence of a new-line character in the result array. Consider using fgets (along with any needed processing based on new-line characters) instead of gets_s.

https://port70.net/~nsz/c/c11/n1570.html#K.3.5.4.1

如果你想使用gets_s,那么使用另一个编译器。或者编写您自己的包装器,但不要将其命名为 gets_s,因为要使其与规范完全相同非常棘手。

C 标准是这样说的:

Runtime-constraints

s shall not be a null pointer. n shall neither be equal to zero nor be greater than RSIZE_MAX. A new-line character, end-of-file, or read error shall occur within reading n-1 characters from stdin.

If there is a runtime-constraint violation, s[0] is set to the null character, and characters are read and discarded from stdin until a new-line character is read, or end-of-file or a read error occurs.

Description

The gets_s function reads at most one less than the number of characters specified by n from the stream pointed to by stdin, into the array pointed to by s. No additional characters are read after a new-line character (which is discarded) or after end-of-file. The discarded new-line character does not count towards number of characters read. A null character is written immediately after the last character read into the array.

If end-of-file is encountered and no characters have been read into the array, or if a read error occurs during the operation, then s[0] is set to the null character, and the other elements of s take unspecified values.

这里有一件事根本没有意义。运行时约束是 s 不应该是空指针。在运行时约束违规时,s[0] 应设置为零。但是如果 s 是一个空指针,操作 s[0] = '\0' 有未定义的行为。

这是我尝试实现它的想法,但 IMO 的规范一团糟,我不相信这一点。要做到这一点很棘手。

char *my_gets_s(char *s, size_t n)
{
    if(!s) return NULL;

    size_t i=0;
    int ch;

    for(i=0; i<n-1; i++) {
        ch = fgetc(stdin);

        // If end-of-file is encountered and no characters have been read into the array,                          
        // or if a read error occurs during the operation, then s[0] is set to the null character                  
        if(ferror(stdin) || (ch == EOF && i == 0)) {
            s[0] = '\0';
            return NULL;
        }

        // If EOF and we have read at least one character                                                          
        if(ch == EOF) {
            s[0] = '\0';
            return s;
        }

        s[i] = ch;

        if(ch == '\n') {
            s[i] = '\0';
            return s;
        }
    }

    while ((ch = getchar()) != '\n' && ch != EOF);
    s[0] = '\0';
    return NULL;
}

关于c - 为什么 `gets_s()` 仍然没有在 GCC (9.3.0) 中实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62976403/

相关文章:

GCC 中的 C11 <thread.h>?

c++ - 使用 GCC 编译 C++ 时如何包含 C11 头文件?

c++ - 使用stat和lstat检测与文件有关的错误

c - Xcode调试期间查看内存中的变量值?

c - 在C中形成数组并打印列/行

c - 如果 -0.0 之后的下一个可表示值是 +0.0,那么为什么 nextafter(-0.0, INFINITY) 不返回 +0.0?

c - 如何解释这行 C 代码中的星号?

c++ - 防止链接器删除导出的函数

c - 算术运算的处理时间不成比例 [C]

linux - 在(CentOS 6.5)2.6.32内核中编译2.4.20内核