C语言 - 为什么在Linux上getopt返回255?

8

最近我一直在使用getopt(来自unistd.h)玩耍。我写了一些代码,在Windows 7上使用MinGW编译器正常运行,但是在我的树莓派上的Raspbian Linux下不工作(我用gcc编译它们两个,没有选项;gcc t.c)。由于某种原因,当面临没有开关时,getopt返回int 255或char ÿ,而实际上应该返回-1。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
  char t;
  opterr = 0;

  while ((t = getopt(argc, argv, "a:")) != -1)
    switch (t) {
      case 'a':
        printf("-a with argument %s\n", optarg);
        return 0;
      case '?':
        printf("uknown option\n");
        return 1;
      default:
        /* This is always 255 under linux, and is never reached under windows */
        printf("getopt returned int %d (char %c)\n", t, t);
        return 2;
    }

  return 0;
}

我有一个想法,实际上在无符号8位算术中,255 就是-1,所以我尝试在while条件语句中放入int强制转换,但这没有起作用。


Getopt() 返回一个整数。将 char t; 改为 int t;,问题就解决了。(-1 表示 EOF,或者在这种情况下表示没有更多的选项。你可以通过添加 case -1: break; 来处理它。) - wildplasser
根据我的 man 手册,自 POSIX.2 以来,getopt 函数从未返回 EOF。当无法找到更多选项时,它会返回 -1。 - Carl Norum
@CarlNorum 我不知道你的意思,请详细说明一下吗? - jacwah
没错。我是以抽象的意义来说,作为EOF 条件,而不是stdio.h中定义的常量。(这与sscanf()使用的返回约定相同,即使输入字符串不是文件) - wildplasser
但是 sscanf 确实会返回 EOF 常量,不是吗?只是在大多数系统上 EOF-1 是巧合。无论如何,这就是我想要澄清的 - 在“文件结尾”的语义和字面使用 EOF 作为常量之间的区别。 - Carl Norum
显示剩余2条评论
1个回答

16
看起来你的系统/工具链默认使用未签名的char类型。这意味着当getopt()返回-1时,它会被转换为255并存储在t中。然后,该255会被提升为int类型(仍为255)并与-1进行比较,这永远无法匹配。 getopt()返回int,因此您应该将t声明为int以匹配,但如果您坚持使用char,则需要使用signed char
另外:由于你说你正在使用gcc编译,如果你想让程序中的其他char变量也是有符号的,你可能会发现-fsigned-char标志很有用。
第二个注意事项:如果你想更容易地调试,也可以通过传递-funsigned-char标志或将t更改为unsigned char来复制失败情况。

作为一个小注释,C程序不需要在main()函数中加上返回语句。 - Dietrich Epp
请公平对待。它有3个返回语句。只是在退出while循环时没有一个返回语句。 - Tom Tanner
非常感谢!我忘记了一个返回语句,但那不是我实际使用的代码,我会进行编辑。 - jacwah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接