анонимный союз в списке инициализаторов, неправильно обрабатывает типы

анонимный союз в списке инициализаторов: неправильно обрабатывать типы

этот код работает странно, я объясню: по пунктам 1 и 2 сказать нечего, работает отлично

однако поведение, указанное в пунктах 3 и 4, изменяется:

1) сначала, если я определяю:

    union {
        uint64_t    integer ;   
        double      real;   
    } ;

компилятор показывает мне ошибку о узком преобразовании между (double) и (uint64_t), но оба имеют одинаковый размер, как вы можете в инструкции утверждения.

C:\prj\cd>g++ -std=c++11 src\prova.cpp -o bin\main.exe
src\prova.cpp: In function 'int main()':
src\prova.cpp:35:6: error: narrowing conversion of '3.3999999999999999e+0' from 'double' to 'uint64_t {aka long long unsigned int}' inside { } [-Wnarrowing]
   t1 = { 1 ,"a",3.4 } ;
  ^

2) во-вторых, если я меняю типы ордеров, компилятор не выдает ошибку, но после выполнения показывает мне неопределенный результат в точке № 4

    union {
        double      real;               
        uint64_t    integer ;   
    } ;

вывод консоли:

C:\prj\cd>bin\main.exe
6.6
3
3.4
4611686018427387904

Мы знаем об ошибках g++ 5.3, ссылающихся на список инициализаторов в c++14, как вы можете найти в bugzilla:

t1 = { 1 ,"a",{ .real=3.4} } ;  

Это еще одна ошибка или странное неопределенное поведение?

здесь другие ссылки о сужении конверсии:

Сужающее преобразование требуется при инициализации списка

Сужение конверсий в С++0х. Это только я, или это звучит как кардинальное изменение?

исходный код :

#include <iostream>
#include <string>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>

typedef struct  token_s
{
    uint8_t         sym ;   
    std::string     tok ;
    union {
        double      real;
        uint64_t    integer ;               
    } ;

} token_t ;

int main ( void )
{
    assert ( sizeof(uint64_t)==sizeof(double) ) ;

    token_t t1 ;

    //#1
    t1.real = 6.6 ; // ok
    std::cout << t1.real << "\n" ;

    //#2
    t1.integer = 3 ; 
    std::cout << t1.integer << "\n" ;

    //#3
    t1 = { 1 ,"a",3.4 } ;   
    std::cout << t1.real << "\n" ;

    //#4
    t1 = { 1 ,"a",2 } ;
    std::cout << t1.integer << "\n" ;   

    return 0 ;
}

person Community    schedule 09.05.2018    source источник
comment
Относительно #4 см. здесь. Поскольку вы опускаете фигурные скобки при инициализации вложенного объединения, оно всегда будет инициализировать первый элемент. Поскольку t1.integer не инициализирован, чтение из него — UB.   -  person 0x5453    schedule 09.05.2018
comment
узкое преобразование между (double) и (uint64_t), но оба имеют одинаковый размер - они могут иметь одинаковый размер по количеству битов, но это не означает, что они оба могут точно представлять одни и те же числа.   -  person Jesper Juhl    schedule 09.05.2018
comment
typedef struct ... Является C-измом. Бессмысленная хрень в C++.   -  person Jesper Juhl    schedule 09.05.2018
comment
src\prova.cpp:95:6: внутренняя ошибка компилятора: в reshape_init_class, в cp/decl.c:5462: t1 = { 1 ,a,{ .integer=2 } } ; g++ 5.1 и g++ 5.3 Win   -  person    schedule 09.05.2018