On-line: гостей 0. Всего: 0 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 20.10.12 19:44. Заголовок: Баг MS VS++2010: некорректное преобразование перечислительной константы


Если скомпилировать и выполнить следующую программу в среде MS VC++ 2010, при этом в свойствах проекта задать значение "Нет" для опции "Отключить расширения языка"

 #include "stdafx.h" 
#include <climits>
#include <iostream>
#include <typeinfo>



int _tmain(int argc, _TCHAR* argv[])
{
std::cout << typeid( UINT_MAX ).name() << std::endl;

enum E { e1 = UINT_MAX, e2, e3 };

std::cout << "\ne1 = " << e1 << std::endl;
std::cout << "e2 = " << e2 << std::endl;
std::cout << "e3 = " << e3 << std::endl;

return 0;
}


то на выходе будет получен следующий результат:


 цитата:
unsigned int

e1 = -1
e2 = 0
e3 = 1



При этом компиляция пройдет без каких-либо предупреждений со стороны компилятора.

Если же задать значение "Да" для опции "Отключить расширения языка" в свойствах проекта, то будет получен тот же результат выполнения программы, но при этом компилятор выдаст несколько следующих предупреждений:


 цитата:
(16): warning C4340: e2: значение из положительного стало отрицательным
(16): warning C4341: e2: значение со знаком лежит вне диапазона для перечисляемых констант
(16): warning C4309: инициализация: усечение константного значения
(18): warning C4309: аргумент: усечение константного значения



Если же этот пример (убрав синтаксические особенности, свойственные MS VC++ 2010) скомпилировать и выполнить с помощью компилятора GCC 4.7.1, то будет получен такой результат:


 цитата:
j

e1 = 4294967295
e2 = 4294967296
e3 = 4294967297



Примечание: В этом выводе буквой j обозначен тип unsigned int. Так как это зависит от реализации, какие обозначения для типов будут выводиться функцией-членом name()

Как видно, получен совершенно другой результат. То есть перечислительные константы при неявном преобразовании к целочисленному типу имеют тот тип, который в состоянии вместить значения UINT_MAX + 1 и UINT_MAX + 2, которые соответствуют перечислительным константам e2 и e3.

Если обратиться к параграфу №3 раздела 4.5 Integral promotions стандарта С++, то можно в нем прочесть следующее


 цитата:
3 A prvalue of an unscoped enumeration type whose underlying type is not fixed (7.2) can be converted to a prvalue of the first of the following types that can represent all the values of the enumeration (i.e., the values in the range bmin to bmax as described in 7.2): int, unsigned int, long int, unsigned long int, long long int, or unsigned long long int.



Кроме того в параграфе № 5 раздела 7.2 Enumeration declarations также написано, что


 цитата:
If the underlying type is not fixed, the type of each enumerator is the type of its initializing value:
— If an initializer is specified for an enumerator, the initializing value has the same type as the expression and the constant-expression shall be an integral constant expression (5.19).
— If no initializer is specified for the first enumerator, the initializing value has an unspecified integral type.
Otherwise the type of the initializing value is the same as the type of the initializing value of the preceding enumerator unless the incremented value is not representable in that type, in which case the type is an unspecified integral type sufficient to contain the incremented value. If no such type exists, the program is ill-formed.



То есть это означает, что для перечислительной константы e2 компилятор должен был назначить тот тип, который вмещает значение UINT_MAX + 1.

Поэтому на мой взгляд имеет место очевидный баг компилятора MS VC++ 2010.

Если у кого уже установлен компилятор MS VC++ 2012, то хорошо бы было узнать, исправлен ли этот баг в новой версии компилятора.

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 1 [только новые]





ссылка на сообщение  Отправлено: 01.04.14 12:47. Заголовок: Как указал Niels Dek..


Как указал Niels Dekker в своем сообщении к отчету о дефекте, посланному мною в Майкрософт, этот баг присутствует и в релизе компилятора MS VC++ 2013.

Вот пример кода, приведенный Niels Dekker, который воспроизводит данный баг в MS VC++ 2013

 
#include <climits>
enum { N = LLONG_MAX };
static_assert( N == LLONG_MAX, "");


Ознакомиться с отчетом можно по ссылке

http://connect.microsoft.com/VisualStudio/feedback/details/768575/deducing-incorrect-underlying-type-for-an-unscoped-enumeration

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 11
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет