Подтвердить что ты не робот

Предупреждение: игнорирование возвращаемого значения "scanf", объявленного с помощью атрибута warn_unused_result

#include <stdio.h>

int main() {
    int t;
    scanf("%d", &t);
    printf("%d", t);
    return 0;
}

Я скомпилировал вышеуказанный код C с помощью ideone.com, и появилось следующее предупреждение:

prog.c: В функции 'main:
prog.c: 5: предупреждение: игнорирование возвращаемого значения 'scanf, объявленный с атрибутом warn_unused_result

Может кто-нибудь помочь мне понять это предупреждение?

4b9b3361

Ответ 1

Писатель вашего libc решил, что в большинстве случаев не следует игнорировать возвращаемое значение scanf, поэтому они дали ему атрибут, сообщающий компилятору дать вам предупреждение.

Если возвращаемое значение действительно не нужно, то вы в порядке. Тем не менее, обычно лучше всего проверить его, чтобы убедиться, что вы действительно успешно прочитали то, что, по вашему мнению, сделали.

В вашем случае код можно написать так, чтобы избежать предупреждения (и некоторых ошибок ввода):

#include <stdio.h>

int main() {
    int t;
    if (scanf("%d", &t) == 1) {
        printf("%d", t);
    } else {
        printf("Failed to read integer.\n");
    }
    return 0;
}

Ответ 2

Предупреждение (правильно) указывает, что плохой идеей не проверять возвращаемое значение scanf. Функция scanf была явно объявлена ​​(через атрибут функции gcc), чтобы вызвать это предупреждение, если вы отмените его возвращаемое значение.

Если вы действительно хотите забыть об этом возвращаемом значении, сохраняя при этом компилятор (и вашу совесть) счастливым, вы можете отбрасывать возвращаемое значение в void:

(void)scanf("%d",&t);

Ответ 3

Я попробовал ваш пример с gcc (Ubuntu 4.4.3-4ubuntu5.1). 4.4.3. Предупреждение выдается тогда и только тогда, когда оптимизация, например, с опцией -O2 или -O3. Запрос всех предупреждений (-Wall) не имеет значения. Классическая идиома литья в void не имеет эффекта, она не подавляет предупреждение.

Я могу отключить предупреждение, написав

if(scanf("%d",&t)){};

это работает, но это немного непонятно для моего вкуса. Пусто {} избегает еще одного предупреждения - Пустое тело

Ответ 4

Сделайте это:

int main() {
    int t;
    int unused __attribute__((unused));
    unused = scanf("%d",&t);
    printf("%d",t);
    return 0;
}

Ответ 5

Одним из способов решения этой проблемы является функция IGUR(), как показано ниже. Чрезвычайно уродливый, но, тем не менее, портативный. (Для старых компиляторов, которые не понимают inline только #define inline /*nothing*/, как обычно.)

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

void inline IGUR() {}  /* Ignore GCC Unused Result */
void IGUR();  /* see /questions/132529/c99-inline-function-in-c-file/795520#795520 */

int
main(int argc, char **argv)
{
  char  buf[10*BUFSIZ];
  int   got, fl, have;

  fl    = fcntl(0, F_GETFL);
  fcntl(0, F_SETFL, fl|O_NONBLOCK);
  have = 0;
  while ((got=read(0, buf, sizeof buf))>0)
    {
      IGUR(write(1, buf, got));
      have = 1;
    }
  fcntl(0, F_SETFL, fl);
  return have;
}

В этом примере неблокированно копирует от stdin до stdout, пока не будет прочитан весь ожидающий вход, возвращая true (0), если ничего не было, else false (1). (Это предотвращает 1s задержку в чем-то вроде while read -t1 away; do :; done в bash.)

Скомпилируется без предупреждения в -Wall (Debian Jessie).

Изменить: IGUR() необходимо определить без inline, чтобы он стал доступен для компоновщика. Else с cc -O0 может завершиться ошибкой. См.: fooobar.com/questions/132529/...

Ответ 6

scanf, printf - это функции, которые возвращают значение, обычно в тех типах функций это количество символов, которые читаются или записываются. если произошла ошибка, вы можете поймать ошибку также с кодом возврата. Хорошая практика программирования будет заключаться в том, чтобы посмотреть на возвращаемое значение, однако я никогда не видел того, кто смотрит на возвращаемое значение printf...

Если вы хотите, чтобы предупреждение исчезло, вы, вероятно, можете изменить серьезность компилятора.

Ответ 7

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

При компиляции с gcc вы можете добавить в свою командную строку:

gcc -Wall -Wextra -Wno-unused-result proc.c -o prog.x

Другой вариант - использовать -O0 как "уровень нулевого уровня оптимизации", игнорирует предупреждение.

Использование приведения в (void) просто бесполезно при компиляции с gcc

Если вы отлаживаете свой код, вы всегда можете использовать assert(), как в приведенном ниже примере:

u = scanf("%d", &t);
assert(u == 1);

Но теперь, если вы отключите assert через #define NDEBUG, вы получите -Wunused-but-set-variable. Затем вы можете отключить это второе предупреждение одним из двух способов:

  • Добавление -Wno-unused-but-set-variable в командную строку gcc или
  • Объявление переменной с атрибутом: int u __attribute__((unused));

Как указано в другом ответе, второй вариант, к сожалению, не очень переносимый, хотя он кажется лучшим вариантом.

Наконец, определенный MACRO ниже поможет вам, если вы уверены, что хотите игнорировать возврат данной функции, но вам не комфортно отключать предупреждения для всех неиспользуемых возвратов функций:

#define igr(x) {__typeof__(x) __attribute__((unused)) d=(x);} 

double __attribute__ ((warn_unused_result)) fa(void) {return 2.2;}
igr(fa());

См. также этот ответ

Ответ 8

На самом деле это зависит от того, что вам нужно, если вы просто хотите отключить предупреждение о компиляторе, вы можете просто игнорировать возвращаемое значение функции путем преобразования силы или вы можете просто обработать ее, значение scanf функция - это подсчет пользовательского ввода.

==== update ====

Вы можете использовать

(void) scanf("%d",&t);

игнорировать возвращаемое значение scanf