Перейти к содержанию
    

bad-function-cast на касте enum -> int

Привет!

собираю в GCC7 такой вот С-код:

printf("mode %d\n", (int)disconnect_mode() );

где `disconnect_mode()` - возвращает enum. 

компилятор ругается:

warning: cast from function call of type 'DisconnectMode {aka enum DisconnectMode}' to non-matching type 'int' [-Wbad-function-cast]

помогает только создать переменную временную, и ей из функции присваивать.

посоветуйте как это можно обойти без кошмаров?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, AlexRayne сказал:

собираю в GCC7 такой вот С-код:


printf("mode %d\n", (int)disconnect_mode() );
printf("mode %i\n", (int)disconnect_mode() );

возможно так

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, heavyC1oud сказал:

printf("mode %i\n", (int)disconnect_mode() );

возможно так

не канает

использую в итоге все же кошмар:

static inline
int TOINT( int x){ return x;}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

48 минут назад, AlexRayne сказал:

где `disconnect_mode()` - возвращает enum. 

Покажите объявление disconnect_mode() и enum. Потому что по правилам языка C enum к int приводится неявно оно должно компилироваться даже без явного приведения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Сергей Борщ сказал:

Потому что по правилам языка C enum к int приводится неявно оно должно компилироваться даже без явного приведения.

да приводится, если это не результат функции. курите  Wbad-function-cast

можно делать временную переменную int и в нее без кастов равнять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, так скажем, покурил:

$ cat tst.c 
#include <stdio.h>

typedef enum my_awesome_enum_e {
    NO,
    YES,
    MAYBE,
} my_awesome_enum_e;

my_awesome_enum_e my_awesome_func( int i );

int main( void ) {
    printf( "value: %d\n", (int)my_awesome_func( 2 ) );
    return 0;
}

my_awesome_enum_e my_awesome_func( int i ) {
    return (my_awesome_enum_e)i;
}
$ gcc -Wall -Wextra -pedantic tst.c 
$ ./a.out 
value: 2

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

37 минут назад, AlexRayne сказал:

да приводится, если это не результат функции.

Можно какое-нибудь подтверждение ваших слов, например - цитату из страндарта?

37 минут назад, AlexRayne сказал:

курите  Wbad-function-cast

Курите сами. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 минут назад, one_eight_seven сказал:

Ну, так скажем, покурил:


$ cat tst.c 

классна, а что за компилятор?
а если явно задать опции -Wbad-function-cast , как оно скомпилит? у меня просто явно добавлена эта опция

Изменено пользователем AlexRayne

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Простите, до этого не то отправил:

#include <stdio.h>

typedef enum my_awesome_enum_e {
    NO,
    YES,
    MAYBE,
} my_awesome_enum_e;

my_awesome_enum_e my_awesome_func( int i );

int main( void ) {
    printf( "value: %i\n", my_awesome_func( 17 ) );
    return 0;
}

my_awesome_enum_e my_awesome_func( int i ) {
    return (my_awesome_enum_e)i;
}
$ gcc -Wall -Wextra -pedantic -Wbad-function-cast tst.c 
$ ./a.out 
value: 17

 

Just now, AlexRayne said:

а если явно задать опции -Wbad-function-cast , как оно скомпилит?

Да, скомпилит, но с warning'ом. Это я не то сначала отправил. Собирался отправить второй экземпляр, с вариантом, о котором писал @Сергей Борщ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, one_eight_seven сказал:

printf( "value: %i\n", my_awesome_func( 17 ) );

ну так вот еслиту не кастить - то все ок , ему нравится. а если явный каст в int поставить , то bad-function-cast заругает 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. дело в том, что явное приведение, действительно, считается компилятором "плохим" если ему говорят так считать.
Т.е. в тестах компилятора прямо есть тест на это - явное приведение енума к инту и наоборот - плохое. Я не копал глубоко, понял так, что enum в общем виде не обязан покрывать 2^32 значений, и будет отруган.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, one_eight_seven сказал:

явное приведение, действительно, считается компилятором "плохим" если ему говорят так считать.

в нетах народ говорит что плохое явное приведение указателя void* к типу, и практика приведения (T*)malloc(...) типа приводит к ошибкам. и вроде как именно с этим кастом они и боролись. а енумы видимо зацепили паровозом.
мой склероз давно потер - чем же это плохо. Но проблемы приведения результата функции к инту вообразить немогу.
если у Вас есть пример - киньте?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, енум - это же совсем не инт. То, как он реализован в C - это одно, а назначение - это совсем другое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"перечисление в целое" вполне безопасное преобразование, т.к. в целевом типе гарантировано есть возможность представления. Протому автоматическое преобразование должно работать без вопросов. А "целое в перечисление" - небезопасное, т.к. в перечислении просто может не оказаться соответствующего значения. И тут требуется явное преобразование, т.е. ответственность перекладывается на программиста.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, dxp сказал:

А "целое в перечисление" - небезопасное, т.к. в перечислении просто может не оказаться соответствующего значения. И тут требуется явное преобразование, т.е. ответственность перекладывается на программиста.

В плюсах. В обычных же сях такое неявное преобразование разрешено.

2 часа назад, dxp сказал:

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

Причем это предупреждение работает только в сях и объективных сях.

Вот тут достаточно внятно написано - зачем это предупреждение и с какими именно проблемами кода оно должно помогать бороться. А именно - с явными приведениями типов в тех местах, где такое приведение не требуется ввиду наличия неявного приведения и ввиду наличия в сях до стандарта 11 года возможности использовать функцию без предварительного объявления, которую компилятор обязан считать возвращающей int. Однако, в таком случае выдается предупреждение об использовании функции без прототипа, которого достаточно для выявления подобных недоработок кода, так что смысла дополнительно включать еще и это предупреждение (а оно может быть включено только принудительно) не видно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...