Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - Why does getopt return 255 on linux?

Tags:

c

getopt

I've been fooling around with getopt (from unistd.h) recently. I wrote some code that worked fine under Windows 7 compiled with gcc from MinGW, while not working under Raspbian Linux on my Raspberry Pi (I compiled them both with gcc, no options; gcc t.c). For some reason getopt returns int 255 or char ÿ when faced with no switches, when really it should return -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;
}

One tought I had was that, actually 255 is -1 in unsinged 8-bit arithmetic, so I tried to put an int cast in the while conditional, but that did nothing.

like image 886
jacwah Avatar asked Jun 12 '13 16:06

jacwah


1 Answers

It looks like your system/toolchain defaults to an unsigned char type. That means when getopt() returns -1, it gets converted to 255 and stored in t. Then that 255 gets promoted to int type (staying 255) and compared to -1, which can't ever match.

getopt() returns int, so you should really declare t as int to match, but if you're set on using char, you're going to need to use signed char.

Aside: Since you say you're compiling with gcc, you might also find the -fsigned-char flag helpful if you want this and other char variables in your program to be signed.

Second Aside: You can duplicate the failure by passing the -funsigned-char flag or by changing t to be an unsigned char in your Windows test, if that makes it easier to debug.

like image 121
Carl Norum Avatar answered Nov 14 '22 12:11

Carl Norum