# Newbie question - convert two 8-byte values into a single 16-byte value

Let’s say I have an array of 2 elements of UInt8.
I need to make it into a single element of UInt16.
How?

I thought about doing bit arithmetic (shifting/or’ing) but there’s got to be an easier way?

You `reinterpret` e.g.

`reinterpret(UInt16, UInt8[1,2])`

1 Like

And if your source has a fixed endianness that might be different from the host byte order of your machine, you can use `ntoh`, `hton`, `ltoh`, and `htol` from `base/io.jl` to convert. E.g. i use this to read a 16-bit big-endian scalar value from the UInt8 array `x`:

``````ntoh(reinterpret(UInt16, x[1:2])[1])
``````
2 Likes

Using arrays to do a little bit of bit manipulation is going to be very inefficient! This is not very hard to write with bit operations:

``````julia> bitcat(a::UInt8, b::UInt8) = (UInt16(a) << 8) | b
bitcat (generic function with 1 method)

julia> bitcat(0x12, 0x34)
0x1234

julia> @code_native bitcat(0x12, 0x34)
.section	__TEXT,__text,regular,pure_instructions
; Function bitcat {
; Location: REPL[23]:1
shll	\$8, %edi
movzbl	%sil, %eax
orl	%edi, %eax
retq
nopw	(%rax,%rax)
;}
``````
5 Likes

Stefan’s remark proven

``````julia> bitcat(a::UInt8, b::UInt8) = (UInt16(a) << 8) | b
bitcat (generic function with 1 method)

julia> bitcat(x::Vector{UInt8}) = (UInt16(x[1]) << 8) | x[2]
bitcat (generic function with 2 methods)
``````

Comparing `reinterpret`, `bitcat` taking individual arguments, and `bitcat` taking an array:

``````julia> @btime reinterpret(UInt16, [0x12, 0x34])
78.048 ns (3 allocations: 176 bytes)
1-element Array{UInt16,1}:
0x3412

julia> @btime reinterpret(UInt16, [0x12, 0x34])
78.280 ns (3 allocations: 176 bytes)
1-element Array{UInt16,1}:
0x3412

julia> @btime reinterpret(UInt16, [0x12, 0x34])
77.307 ns (3 allocations: 176 bytes)
1-element Array{UInt16,1}:
0x3412

julia> @btime bitcat([0x12, 0x34])
39.327 ns (1 allocation: 96 bytes)
0x1234

julia> @btime bitcat([0x12, 0x34])
39.276 ns (1 allocation: 96 bytes)
0x1234

julia> @btime bitcat([0x12, 0x34])
39.401 ns (1 allocation: 96 bytes)
0x1234

julia> @btime bitcat(0x12, 0x34)
1.760 ns (0 allocations: 0 bytes)
0x1234

julia> @btime bitcat(0x12, 0x34)
1.759 ns (0 allocations: 0 bytes)
0x1234

julia> @btime bitcat(0x12, 0x34)
1.760 ns (0 allocations: 0 bytes)
0x1234
``````

Actually I’m surprised that the array version is only 20x slower. If you’re using `@btime` for timing I think you can just do it once since the whole purpose of that macro is to run something enough times for you automatically – and note that it seems to be working since the measurements of the same operation are all similar.

Do be careful with

``````@btime bitcat([0x12, 0x34])
``````

Note that

``````julia> @btime bitcat(\$([0x12, 0x34]))
1.791 ns (0 allocations: 0 bytes)
0x1234
``````

and

``````julia> @btime bitcat(x) setup = x = rand(UInt8, 2)
1.737 ns (0 allocations: 0 bytes)
0xd87b
``````