【问题标题】:Compiler error for signedness in CC中签名的编译器错误
【发布时间】:2024-01-05 04:24:01
【问题描述】:

我对 C 语言比较陌生,在编译一个可以运行的程序后,我收到了一些编译器警告。

警告说:

main.c: In function ‘lsh_read_line’:
main.c:65:2: warning: pointer targets in passing argument 2 of ‘getline’ differ in signedness [-Wpointer-sign]
    getline(&line, &bufsize, stdin);
    ^
char *lsh_read_line(void)
{
    char *line = NULL;
    ssize_t bufsize = 0;
    getline(&line, &bufsize, stdin);
    return line;
}

我看到的大多数解决方案都建议在分配缓冲区空间时使用指针,但我只是让 getline 自己分配内存,所以我不知道如何纠正这个问题。

另外,我认为这个警告是相关的,但我不知道它的含义或如何纠正它:

In file included from main.c:4:0:
/usr/include/stdio.h:678:20: note: expected ‘size_t * __restrict__’ but argument is of type ‘ssize_t *’
 extern _IO_ssize_t getline (char **__restrict __lineptr,
                    ^

【问题讨论】:

  • 有什么理由不使用正确的类型(size_t)吗?
  • 赞成尝试解决警告,即使程序“运行良好”。

标签: c compiler-warnings


【解决方案1】:

ssize_tsize_t 是不同的类型。 size_t是无符号整数类型,即sizeof的返回类型和*allocfread/fwrite等函数的参数类型; size_t 在 C 标准中定义。

另一方面,

ssize_t 是一个有符号 整数类型。它不是 C 标准的一部分,但在 POSIX 中用作函数的返回类型,例如返回写入/读取的字节数,或错误时返回负值。

您不应将这两种类型相互混淆。注意getline 返回ssize_t 但需要一个指向size_t 的指针:

ssize_t getline(char **lineptr, size_t *n, FILE *stream);

getline 返回读取的字符数,但*n 将包含分配给缓冲区的字节数。返回值是 ssize_t 类型 - 一个有符号整数 - 因此可以返回错误 -1。另一方面,size_t*alloc 函数的参数类型;如果*lineptr 不为空,则说明*n 应指向*lineptr 的现有内存分配大小。

因此

char *lsh_read_line(void)
{
    char *line = NULL;
    size_t bufsize;
    ssize_t n_read = getline(&line, &bufsize, stdin);
    if (n_read < 0) {
        // handle error condition?
        // then maybe:
        return NULL;
    }
    return line;
}

虽然有些人声称它们“只是”警告,但关于 C 编译器警告的真相通常是它们在某些情况下可能是严重错误,并导致您的程序具有未定义的行为

【讨论】:

  • 感谢您的帮助!这无疑提高了我对 getline 的理解。
  • 如果可以的话,你应该重用分配的内存(因为你需要跟踪size_t n,它有助于避免堆碎片。
【解决方案2】:

错误表明它需要 size_t* 而不是 ssize_t*

尝试将ssize_t bufsize = 0; 更改为size_t bufsize = 0;

【讨论】: