how to use a union

So I'm going to get right to the point asking what I need to know. I'll explain the reasoning below. I am new to c++ and not very accustomed to unions and structures yet. I'm not sure if this can be done but this is what I am trying to do.

I want to create a union which will have the following members

1. a character array of a size to be later declared
2. a two dimensional array created to divide the first array in to 512-bit blocks
3. an array of 32-bit words within each of the blocks
is this possible?

explanation.

I am trying to create my own sha-256 algorithm according to FIPS180-4
http://csrc.nist.gov/publications/drafts/fips180-4/Draft-FIPS180-4_Feb2011.pdf
see section 5.1


So far I have managed to create a character array of (N * 512) bits containing the padded message. It seems to me that the most efficient way is with pointers to each 512 bit block and each 32 bit word.

any advice?
You do know that trying to read variable other than last written is UB, right:
1
2
3
4
5
6
7
8
9
union foo
{
    double d;
    uint64_t i; //Hoping to get binary representation of d
};

foo x;
x.d = 9.31;
std::cout << x.f; //Undefined behavior  
> is this possible?

Yes. Any object may be examined as a sequence of bytes.

And for a complete object of a trivially copyable type, the underlying bytes making up the object can be copied into and later restored from an array of bytes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <limits>
#include <cstdint>
#include <cstring>

constexpr std::size_t BITS_PER_OCTET = 8 ;
static_assert( std::numeric_limits<unsigned char>::digits == BITS_PER_OCTET,
                                                          "byte is not an octect" ) ;
constexpr std::size_t BITS_PER_BLOCK = 512 ;
constexpr std::size_t BYTES_PER_BLOCK = BITS_PER_BLOCK / BITS_PER_OCTET ;

union block
{
    char bytes[BYTES_PER_BLOCK] ;
    std::uint32_t words[ BYTES_PER_BLOCK / sizeof(std::uint32_t) ] ;
};

template < std::size_t NBITS > union msg_chunk
{
    static_assert( NBITS % BITS_PER_BLOCK == 0, "bad size" ) ;

    char bytes[ NBITS / BITS_PER_OCTET ] {} ;
    block blocks[ sizeof(bytes) / sizeof(block) ] ;
};

int main()
{
    msg_chunk<4096> msg ;
    for( block& b : msg.blocks )
    {
        int v = 0 ;
        for( std::uint32_t& w : b.words ) w = v++ ;
    }

    char temp[ sizeof(msg) ] ;
    std::memcpy( temp, msg.bytes, sizeof(msg) ) ;
    std::memset( msg.bytes, 0, sizeof(msg) ) ;
    std::memcpy( msg.bytes, temp, sizeof(msg) ) ;

    for( block& b : msg.blocks )
    {
        for( std::uint32_t& w : b.words ) std::cout << w << ' ' ;
        std::cout << '\n' ;
    }
}

http://coliru.stacked-crooked.com/a/f72059f222cf97bf
Last edited on
Topic archived. No new replies allowed.