gcc: как обнаружить неправильное использование `bool` - PullRequest
8 голосов
/ 16 марта 2019

Есть ли способ обнаружить неправильное использование значений bool в коде, подобном

#include <stdbool.h>

void *foo(void)
{
    return false;
}

int bar(void)
{
    return true;
}

Обе функции принимаются gcc (8.3.1) и clang (7.0.1) без каких-либо предупреждений

$ gcc -Wall -W -pedantic -c x.c
$ clang -Xclang -analyzer-checker=alpha --analyze  -Wall -W -pedantic -c x.c
$ clang -Wall -W -pedantic -c x.c
$

Компиляция кода C ++ выявила бы проблему в foo(), но это не вариант, но остальная часть кода - C, а не C ++.

Существуют ли другие (-W) опции или переключатели, которые могли бы создать диагностику для этих случаев?

Ответы [ 2 ]

2 голосов
/ 16 марта 2019

Сделайте пример менее тривиальным:

bool x;

void *foo(void)
{
    return x;
}

int bar(void)
{
    return x;
}

, и он вообще хочет компилироваться.

обычно true и false являются просто определениями и имеют значения 1 и 0

Из заголовочного файла stdbool.h

#ifndef _STDBOOL_H
#define _STDBOOL_H

#ifndef __cplusplus

#define bool    _Bool
#define true    1
#define false   0

#else /* __cplusplus */

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

1 голос
/ 16 марта 2019

C определяет макросы <stdbool.h> true и false как расширение до целочисленных константных выражений значения 1 и 0 соответственно.Поскольку они int s и bool (_Bool) сами по себе являются целочисленным типом, любое такое использование в равной степени допустимо.Даже значение логических выражений в C равно int, а не bool, поэтому вам не очень поможет функция bar.

Однако foo - это другоеbeast - если бы возвращаемое значение было true, то оно было бы сразу поймано, потому что 1 не конвертируется в указатель.false, имеющее целочисленное значение 0 равно константе нулевого указателя и будет преобразовано в нулевой указатель.Возможно, вы могли бы уловить неправильное использование, заменив #include <stdbool.h> чем-то, что делает включение, но определяет false как, скажем, 0.0, что является ложным значением, но не целочисленным константным выражением.

...