C - Почему getopt возвращает 255 в Linux?

Недавно я баловался с getopt (из unistd.h). Я написал некоторый код, который отлично работал под Windows 7, скомпилированный с помощью gcc из MinGW, но не работал под Raspbian Linux на моем Raspberry Pi (я скомпилировал их оба с помощью 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;
}

У меня была одна мысль, что на самом деле 255 равно -1 в неподписанной 8-битной арифметике, поэтому я попытался поместить приведение типа int в условное выражение while, но это ничего не дало.


person jacwah    schedule 12.06.2013    source источник
comment
Getopt() возвращает целое число. измените char t; на int t; и все будет в порядке. (-1 будет означать EOF или, в данном случае: больше никаких опций. Вы можете справиться с этим, добавив case -1: break;)   -  person wildplasser    schedule 12.06.2013
comment
Согласно моей справочной странице, getopt не возвращал EOF со времен POSIX.2. Он возвращает -1, когда не может найти больше вариантов.   -  person Carl Norum    schedule 12.06.2013
comment
@CarlNorum Я понятия не имею, что вы имеете в виду, не хотите уточнить?   -  person jacwah    schedule 12.06.2013
comment
wildplasser упомянул EOF, и я просто хотел уточнить, что фактическая константа EOF из stdio.h не возвращается getopt и не возвращается с 1992 года или около того.   -  person Carl Norum    schedule 12.06.2013
comment
Ну, я думаю, что он имеет в виду EOF как «конец файла» или, скорее, конец ввода, а не это.   -  person jacwah    schedule 12.06.2013
comment
Точно. Я имел в виду это в абстрактном смысле, как условие EOF, а не как определенную константу из stdio.h. (Это то же соглашение о возврате, которое использует sscanf(), хотя входная строка не является файлом)   -  person wildplasser    schedule 12.06.2013
comment
Но sscanf возвращает константу EOF, не так ли? Это просто совпадение, что EOF в большинстве систем равно -1. Во всяком случае, это уточнение, которое я хотел сделать - между семантикой конца файла и буквальным использованием EOF в качестве константы.   -  person Carl Norum    schedule 13.06.2013


Ответы (1)


Похоже, что ваша система/инструментальная цепочка по умолчанию использует беззнаковый тип char. Это означает, что когда getopt() возвращает -1, оно преобразуется в 255 и сохраняется в t. Затем этот 255 становится типом int (оставаясь 255) и сравнивается с -1, который никогда не может совпадать.

getopt() возвращает int, поэтому вам действительно следует объявить t как int для соответствия, но если вы настроены на использование char, вам нужно будет использовать signed char.

В сторону: поскольку вы говорите, что компилируете с помощью gcc, вам также может пригодиться флаг -fsigned-char, если вы хотите, чтобы эта и другие переменные char в вашей программе были подписаны.

Второе замечание: вы можете продублировать ошибку, передав флаг -funsigned-char или изменив t на unsigned char в своем тесте Windows, если это упрощает отладку.

person Carl Norum    schedule 12.06.2013
comment
Небольшое замечание: программы на C не требуют, чтобы main() имел оператор возврата. - person Dietrich Epp; 12.06.2013
comment
будь честен. он имеет 3 оператора возврата. у него просто нет такого, когда он выпадает из цикла while. - person Tom Tanner; 12.06.2013
comment
Большое спасибо! Я забыл оператор возврата, но это не тот код, который я использовал, но я его отредактирую. - person jacwah; 12.06.2013