mercredi 9 mai 2018

anonymous union in initializer list, do not handle the types correctly

anonymous union in initializer list : do not handle the types correctly

this code works weirdly, I'll explain : nothing to say regards points 1 and 2, works perfeclty

however the behavior referred to points 3 and 4 changes :

1) first if i define :

    union {
        uint64_t    integer ;   
        double      real;   
    } ;

compiler shows me error about narrow conversion between (double) and (uint64_t), but both have same size, as you can in in assert instruction.

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) second if i change order types, compiler do not emits error but after execution show me undefined result at point #4

    union {
        double      real;               
        uint64_t    integer ;   
    } ;

console output :

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

We know about g++ 5.3 bugs referring initializer list in c++14, as you can found in bugzilla :

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

Does is this another bugs or an weirdly undefined behavior ?

here others link about narrowing conversion :

Narrowing Conversion required while list initialization

Narrowing conversions in C++0x. Is it just me, or does this sound like a breaking change?

source code :

#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 ;
}

Aucun commentaire:

Enregistrer un commentaire