gcc сообщает "никогда не будет выполнено" о строке: while(fgets(line, MAX_LINE, stdin)!= NULL)

Я ищу объяснение, почему gcc дают это предупреждение для меня.

Я собираю с gcc-3 на cygwin с -Wunreachable-code флаг, и GCC говорит это предупреждение для меня:

main.c: 223: предупреждение: никогда не будет выполнено

Вот эта строка: while(fgets(line, MAX_LINE, stdin) != NULL) {

Этот код находится внутри if(exp) { } блок где exp динамически устанавливается в соответствии с аргументами командной строки (анализируется getopt()), посмотрите на часть кода:

 if(mystruct.hastab) {

значение по умолчанию 0, Но это стало 1 если -t флаг передается приложению, как вы можете видеть по следующему адресу:

struct mystruct_t {
   //... 
   int hastab;
} mystruct;

    int main(int argc, char *argv[])
    {

      int opt;
        memset(&mystruct, 0, sizeof(mystruct));
         while((opt = getopt(argc, argv, optString)) != -1) {
            switch(opt) {
              case 't':
               mystruct.hastab = 1;
               break;
              //....
            }
        }
         proc();
        return 0;
    }

    void 
    proc(void)
    {
      char *buf, *tmpbuf, line[MAX_LINE + 1], *p, *fullfilename;

      if(mystruct.hastab) {

        while(fgets(line, MAX_LINE, stdin) != NULL) {
           //...
        }
      } else {
       //...
      }
    }

Итак, есть причина для выполнения кода. Как бывает.

3 ответа

Решение

Вот еще одна возможность: проблема с макросами. Вот простой пример, который демонстрирует вашу ошибку:

#include <string.h>
int s;
int main(int argc, char *argv[]) {
  memset(&s, 0, sizeof(s));
}

Когда я компилирую это, я получаю:

$ gcc -Wunreachable-code tmp.c
tmp.c: In function ‘main’:
tmp.c:4: warning: will never be executed

Ошибка не особенно поучительна. Однако, если вы запустите препроцессор, посмотрите, что memset расширяется до:

$ gcc -E tmp.c

...
int s;
int main(int argc, char *argv[]) {
  ((__builtin_object_size (&s, 0) != (size_t) -1) ? __builtin___memset_chk (&s, 0, sizeof(s), __builtin_object_size (&s, 0)) : __inline_memset_chk (&s, 0, sizeof(s)));
}

Я подозреваю, из-за постоянного размера sтолько одна из ветвей ?: когда-либо выполняется, и это то, на что жалуется GCC. В вашем случае, это, вероятно, fgets это макрос. Бежать gcc -Eнайдите в выходной строке свою проблему и посмотрите, не шатается ли она (у меня нет, но я не запускаю cygwin).

Мораль истории: препроцессоры и макросы сосут.

Похоже, GCC убежден hastab никогда не устанавливается или устанавливается только после кода, о котором предупреждает. Конечно, кажется, что gcc не прав, но так как вы дали нам только фрагменты, трудно быть уверенным. Я не думаю, что кто-то может помочь вам дальше, если мы не увидим полную программу, которую мы можем составить сами.

Если бы мне пришлось угадывать, я бы сказал, что gcc рассматривает 2 случая, когда вы можете позвонить proc() не задав mystruct.hastab к чему-то другому, чем 0,

Первый случай, если это соответствует false при первом запуске, так как вы будете выпадать из цикла без выполнения switch заявление:

while((opt = getopt(argc, argv, optString)) != -1) {

Второй случай, если opt никогда 't':

switch(opt) {
case 't':
    mystruct.hastab = 1;

Таким образом, вы выпадете из цикла, даже не ставя mystruct.hastab к ненулевому значению.

Другие вопросы по тегам