Есть ли предупреждение для назначения переменной enum со значением вне диапазона enum? - PullRequest
1 голос
/ 23 января 2020

У меня есть функция C, которая использует enum в качестве параметра, как в примере ниже:

typedef enum
{
  AB, 
  CD
} A;

void f(A input)
{
  // do something
}

int main(void)
{
   // do something
   f(-10);
   // do something
}

Есть ли предупреждение, которое можно включить для назначения переменной enum со значением out диапазона перечисления?

Ответы [ 3 ]

5 голосов
/ 23 января 2020

В базе данных ошибок G CC есть открытая ошибка для него . Похоже, что G CC пока не содержит такой функции. Есть опция под названием -Wc++-compat, которая будет жаловаться - среди множества других вещей, около любое целое число неявно преобразуется в тип enum.

Связанная функция имеет просто приземлился в хранилище G CC. В транке G CC (но не в 9.2.1, который является компилятором Ubuntu 19.10), есть переключатель -Wenum-conversion, который будет предупреждать об использовании несвязанного значения перечисления, но не голого целого числа; то есть с кодом ниже он будет предупреждать о вызове функции последний , но не первый. :

typedef enum{ AB, CD } A;

typedef enum{ EF, GH } B;

void f(A input){
    (void)input;
}

int main(void){
    f(-10);
    f(GH);
}

Диагностика от компиляции с -Wenum-conversion будет быть

<source>: In function 'main':
<source>:18:6: warning: implicit conversion from 'enum <anonymous>' to 'A' [-Wenum-conversion]
   18 |    f(GH);
      |      ^~
2 голосов
/ 23 января 2020

Даже если enum является определяемым пользователем типом, он переводится компилятором как примитив, в моем случае int, вы можете проверить его с помощью:

#include <stdio.h>

#define printHelloIfEnumIsInt(x) \
    _Generic(x, int: puts("Hello"));

typedef enum {
  AB, 
  CD
} A;

int main(void)
{
    printHelloIfEnumIsInt(AB);
    return 0;
}

возвращает:

Hello

, поэтому допускается любое значение в диапазоне INT_MIN ... INT_MAX.

0 голосов
/ 23 января 2020

Не думаю, что есть хороший способ сделать это. Но, при условии, что вы не используете = в своем перечислении, например enum foo {a=0, b=4}, вы можете сделать это следующим образом:

typedef enum{
  AB, 
  CD,
  A_max // Extra field that should be last
} A;

void f(A input){
    assert(input >= 0 && input < A_max);
    //  Do something
}

Это работает, потому что, если = не используется, первый элемент будет ноль, и все последующее добавит 1 для каждого из них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...