initializing unions

Hi, the code below gives me an error: too many initializers, referring to the union initializing line. Why is it incorrect and what what should I do instead? Thanks.

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
  #include <iostream>
#include <string>
#include <sstream>

using namespace std;

struct struct_example
{
	int integer;
	float decimal;
	char name[20];
};

union union_example
{
	int integer;
	float decimal;
	char name[20];
};

int main() {
	struct_example s = { 18,38,"hello" };
	union_example u = { 18,38,"hello" };
	cout << s.decimal << endl;
	cout << u.name;
	cin.get();
};


Also, in this next code, an error is thrown: array type 'char[20]' is not assignable. Isn't 'name' a C-string? How to assign it?
1
2
3
4
5
6
7
8
9
10
11
12
13
struct struct_example
{
	int integer;
	float decimal;
	char name[20];
} s;

int main() {
	s.name = "hello";
	cout << s.name << endl;
	cin.get();
};
Why is it incorrect and what what should I do instead?
A union is not a struct. A union can only be initialiized by a single value.

Isn't 'name' a C-string?
Yes, therfore you cannot assign it.
How to assign it?
Use strcpy(...).
union_example u = { .name={ 'h', 'e', 'l', 'l', 'o', '\0' } };

But, admittedly, turn the compiler error messages up and my g++ compiler says:
try2.cpp: In function 'int main()':
try2.cpp:23:29: warning: C++ designated initializers only available with -std=c++2a or -std=gnu++2a [-Wpedantic]
union_example u = { .name={ 'h', 'e', 'l', 'l', 'o', '\0' } };

Works beautifully in cpp.sh, though!
Last edited on
> what should I do instead?

Use std::variant (with std::string instead of the c-style array):
https://en.cppreference.com/w/cpp/utility/variant

Or if a home-grown union must be used, consider making it a union-like class:
https://en.cppreference.com/w/cpp/language/union#Union-like_classes
For example:
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
#include <iostream>
#include <cstring>

struct example
{
    enum type { INT, FLOAT, CSTR };

    type current ;

    union
    {
        int integer;
	    double decimal;
	    char name[20];
    };

    example( int i = 0 ) : current(INT), integer(i) {}
    example( double d ) : current(FLOAT), decimal(d) {}
    example( const char* cstr ) : current(CSTR) { std::strcpy(name,cstr) ; }

    friend std::ostream& operator<< ( std::ostream& stm, const example& e )
    {
        switch(e.current)
        {
            case INT : return stm << "INT: " << e.integer ;
            case FLOAT : return stm << "FLOAT: " << e.decimal ;
            case CSTR : default: return stm << "CSTR: " << e.name ;
        }
    }

};

int main()
{
    example a ; std::cout << a << '\n' ; // INT, 0
    example b = 4 ; std::cout << b << '\n' ; // INT, 4
    example c = 6.8 ; std::cout << c << '\n' ; // FLOAT, 6.8
    example d = "hello!" ; std::cout << d << '\n' ; // CSTR, "hello!"

    c = "hello again!" ; // CSTR, "hello again!"
    std::cout << c << '\n' ; // CSTR, "hello again!"
}

http://coliru.stacked-crooked.com/a/12fecfbba90fd5ef
Topic archived. No new replies allowed.