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

Кастинг в пустоту не удаляет ошибку warn_unused_result

В тесте я отбрасываю что-либо из stderr, поскольку он загромождает вывод тестового примера. Я использую следующий код:

freopen("/dev/null", "w", stderr);

При компиляции с -Wall -Werror, я получаю ошибку

error: ignoring return value of ‘freopen’, declared with attribute warn_unused_result

который ожидается. Однако обычное решение литья на void, похоже, не работает. То есть, изменив код на

(void) freopen("/dev/null", "w", stderr);

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

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

UPDATE: Я решил пойти с этим:

FILE *null = fopen("/dev/null", "w");
if (null) { fclose(stderr); stderr = null; }

После более детального изучения документации freopen, я вижу, что если сбой /dev/null не удался, stderr все равно будет уничтожен. Это решает эту проблему.

4b9b3361

Ответ 1

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

if (freopen("/dev/null", "w", stderr) == 0)
    ...oops...lost stderr...hard to report errors...

Так как функция объявлена ​​с атрибутом "warn_unused_result", вы получите предупреждение, если не используете возвращаемое значение. Поскольку функция либо возвращает значение null при ошибке, либо аргумент файлового потока при успешном завершении, вы можете подумать о назначении результата. Однако вы не должны назначьте stderr, как это (см. ниже), так что это плохая идея:

stderr = freopen("/dev/null", "w", stderr);

Теоретически, вы должны сделать эту проверку; есть ужасные (и неправдоподобные) обстоятельства, при которых вы не можете открыть "/dev/null".


Сноска 229 в стандартных примечаниях C99:

229) Основное использование функции freopen заключается в изменении файла, связанного со стандартным текстовым потоком (stderr, stdin или stdout), так как эти идентификаторы не должны быть модифицируемыми значениями, значения которых возвращаемый функцией fopen, может быть назначен.

Следовательно, назначение не рекомендуется. Но тестирование возвращаемого значения будет иметь отношение к предупреждению компилятора и может помочь предотвратить сброс базы. Это вряд ли улучшит ваши показатели покрытия кода, хотя (путь ошибки не будет приниматься очень часто, будет сложно заставить охватить обработку ошибок).

Обратите внимание, что описание POSIX freopen() содержит некоторые умеренно каустические комментарии о дизайне freopen(), который был изобретен C (версия 1989 г.), предположительно без ввода POSIX.

Ответ 2

Немного тяжело на расширениях GCC, но нет видимых извне переменных:

#define ignore_result(x) ({ typeof(x) z = x; (void)sizeof z; })
ignore_result(freopen("/dev/null", "w", stderr));

Ответ 3

int tossmeout = freopen("/dev/null", "w", stderr);

В качестве комментариев ниже попробуйте

FILE *tossmeout = freopen("/dev/null", "w", stderr);

и

(void *)freopen("/dev/null", "w", stderr);

Ответ 4

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

inline void ignore_result_helper(int __attribute__((unused)) dummy, ...)
{
}

#define IGNORE_RESULT(X) ignore_result_helper(0, (X))

Например

typedef struct A
{
    int x;
} A;

__attribute__((warn_unused_result)) A GetA()
{
    A const a;
    return a;
}

int main()
{
    IGNORE_RESULT(GetA());
    return 0;
}