Looking at the output of the assembly, we will see a discrepancy in the two files.
In test_nativ :
86ec: 4602 mov r2, r0 86ee: 460b mov r3, r1 86f0: f241 0044 movw r0, #4164 ; 0x1044 86f4: f2c0 0001 movt r0, #1 86f8: f7ff ef5c blx 85b4 <_init+0x20>
This passes double in r2:r3 and std::cout in r0 .
In test_cc :
86d8: e28f3068 add r3, pc, #104 ; 0x68 86dc: e1c320d0 ldrd r2, [r3] 86e0: e14b21f4 strd r2, [fp, #-20] ; 0xffffffec 86e4: e3010040 movw r0, #4160 ; 0x1040 86e8: e3400001 movt r0, #1 86ec: ed1b0b03 vldr d0, [fp, #-12] 86f0: ebffffa5 bl 858c <_init+0x20>
This passes double to d0 (VFP register) and std::cout to r0 . Note that r2:r3 loads (via ldrd ) with a floating point value that prints second, i.e. 0.0. Since the dynamically linked ostream::operator<<(double val) expects its argument in r2:r3 , 0 is output first.
I can explain the second weird floating point view. Here, where the second float is printed:
8708: e1a03000 mov r3, r0 870c: e1a00003 mov r0, r3 8710: ed1b0b05 vldr d0, [fp, #-20] ; 0xffffffec 8714: ebffff9c bl 858c <_init+0x20>
See that r3 set to r0 , the address is cout . Above, r0 = 0x011040 . Thus, the pair of registers r2:r3 becomes 0x0001104000000000, which decodes to 1.478946186471156e-309 as double.
Thus, the problem is that your GCC computers on your computer use VFP / NEON instructions that are not used by the dynamic libraries on the device. If you use -static , you get the VFP / NEON libraries, and everything works again.
My suggestion would be to simply find out why the device and compiler libraries are different, and find out that they are sorted.