This question already has answers here:
Accessing inactive union member and undefined behavior?
(5 answers)
Closed 2 years ago.
For the following code
#include <iostream>
using namespace std;
union type
{
int a;
char b ;
};
int main()
{
type first;
first.b = 'a';
cout << first.a << " " << first.b << endl;
}
the output is -858993567 a (MSVC) or 4201057 a(g++ MINGW).
but for
#include <iostream>
using namespace std;
union type
{
int a;
char b ;
};
int main()
{
type first;
first.a = 0;
first.b = 'a';
cout << first.a << " " << first.b << endl;
}
the output is 97 a
And these values are fixed under every circumstances (tried rebooting and creating new workspace/file, hence not garbage values).
So, why did the initialization (in the second case) made a difference?
I have tried it both on visual studio (using MSVC) and visual studio code (using g++).
Update 1
I checked on online IDE which probably use Linux g++, and they give the exact expected answer i.e., 97 a, in both the cases.
If you specify first.a in first code sample - you will get fixed, stable value.
You have union with 4 bytes size and initialize only one byte of them.
Union is like type who can holds any type but this types musts be writed in definition of union, like this:
union Example {
char a;
std::int32_t b;
};
Example ex; /// Create object of union
ex.a = 'c'; /// At this moment a member is valid and b is invalid
std::cout << ex.b; /// This cause undefined behavior
Be aware, size of union object is size of type who need most bytes. In this case size is same as size of b property.
Related
This question already has answers here:
Why is the address of this volatile variable always at 1?
(3 answers)
Closed 3 years ago.
In our code we use pointers to structures to deduct addresses of hardware registers to keep the code readable.
For example:
#include <cstdint>
#include <iostream>
struct reg {
uint32_t t;
uint32_t x;
uint32_t value;
};
int main(void)
{
struct reg *r = reinterpret_cast<struct reg *>(0x800000);
std::cerr << &r->value << "\n";
std::cerr << &r->t << "\n";
std::cerr << &r->x << "\n";
return 0;
}
The hardware-base-address is 0x800000 and using writeReg(&t->x, 123); will make it write to 0x800004.
By accident a volatile-keyword was wrongly placed in the structure-definition:
struct reg {
volatile uint32_t t;
volatile uint32_t x;
volatile uint32_t value;
};
What happened now is that all fields have the offset 1 using the &r->field-syntax.
Using g++ (Debian 9.2.1-4) 9.2.1 20190821 here.
Rewriting the test in C using printf and a C-style-cast gives again the correct offset even with volatile.
I'm unable to unable to understand why the volatile-keyword seems to break pointer-arithmetic? Why is that so? What is happening?
There is no overload of operator<< for printing pointers to volatile.
The best suitable overload your compiler finds is the one for printing bool, so your pointers get converted to bool.
Try:
std::cerr << (void *)&r->value << "\n";
C++11 allows an anonymous union to be defined in a function, and its members can be accessed as variables of the function. If I examine the pointers to the different members, they are the same, but the == operator says they're unequal.
Such strange behavior is typically the result of undefined behavior, but I don't see anything undefined in my code (I made sure to that both members are of the same type).
The behavior is different if I use a named variable of an unnamed union type. In this case, the pointers compare equal.
This program demonstrates both cases:
#include <iostream>
using namespace std;
#ifdef NAMED
// Create a named object of a union type
#define NAME n
#define ADDR(mem) &(NAME.mem)
#else
// Create an anonymous union in main()
#define NAME
#define ADDR(mem) &mem
#endif
int main()
{
union {
int a;
int b;
} NAME;
cout << "&a = " << ADDR(a) << endl;
cout << "&b = " << ADDR(b) << endl;
cout << "(&a==&b) = " << (ADDR(a) == ADDR(b)) << endl;
return 0;
}
When compiled with -DNAMED it prints to identical pointers, and 1 (equal pointers). Without -DNAMED, it again prints identical pointers, but then 0 (unequal pointers).
Tested with g++ 5.4.0, Ubuntu 16.04, x86_64.
Your address checking is well defined (as YSC pointed out) and the standard guarantees that all members shall have the same address (cfr. [class.union]/3).
You must have stumbled upon a now fixed compiler bug.
Consider this snippet:
#include<iostream>
struct S {
int bf1:16, bf2:7;
char bf3:8;
} s;
struct A{
int i;
char c;
};
int main() {
std::cout << sizeof(S) << '\n';
std::cout << sizeof(A) << '\n';
}
clang and GCC print the following values for the code above (see live example):
4
8
That is, it allocates the bit-field bf3 as if I had defined struct S as follows:
struct S{
int bf1:16, bf2:7, bf3:8
};
That doesn't seem to be correct.
Note also, that if I define the bit-field bf3 with 9 bits, in the original snippet, both compilers emit a warning saying that the 9 bits exceed the width of its type, a char, but now they print 8 bytes for the struct S. That's strange, as it's still possible to allocate the 9 bits, as if bf3 was declared in the first int member of the struct.
I know the Standard says in [class.bit]/1 that:
Allocation of bit-fields within a class object is
implementation-defined.
Maybe I'm missing something, but I think there is some inconsistency in the way both compilers are treating this case.
This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 6 years ago.
I have these two almost identical bits of c++
#include <iostream>
using namespace std;
int main(){
int a = 0;
int b = 1;
int c = 2;
int d = 3;
int *p = &a;
cout << &c << endl;
cout << *(p+1);
}
with the output:
0x7ffd7b16998c
2
and
#include <iostream>
using namespace std;
int main(){
int a = 0;
int b = 1;
int c = 2;
int d = 3;
int *p = &a;
cout << &d << endl;
cout << *(p+1);
}
which produces the output:
0x7ffdb7ea105c
3
Why does the value of *(p+1) depend on what I output beforehand?
If I delete the line
cout << &c << endl;
completely i get the expected 1 as an output.
What on earth is happening?
What's happening is undefined behavior.
When you obtain a pointer to an int, you are allowed to use the value of that pointer alone; pointer arithmetic is meaningless.
In order for p+1 to produce an address that you can dereference, p must point to an array element other than its last element. In all other situations, reading *(p+1) is undefined.
Standards aside, the CPU must be taking that value from some place. You assume that the place must be the address of b, which is declared immediately after a. However, C++ makes no guarantees about location of local variables in memory relative to each other. It appears that the compiler reorders your variables, producing an output that you did not expect (and it's undefined anyway).
*(p+1) accesses memory after a so it's Undefined Behaviour.
Propably you intended (*p)+1 to increase a by 1?
This question already has answers here:
Accessing inactive union member and undefined behavior?
(5 answers)
Closed 6 years ago.
Declaring variable without initializing it will have a garbage value so in this program I am using a union:
union un
{
int value;
char c;
};
int main()
{
un x;
x.c = 'A';
cout << x.value << endl; // garbage: ok
}
above it is ok when printing value it produces a garbage value as long as we didn't initialize it.
but look at this program:
union un
{
int value;
char c;
}r;
int main()
{
r.c = 'A';
cout << r.value << endl; // 65! as we know the ASCII value of character 'A' is 65
}
so what is the difference between the two program above and why in the second one value gets the value of c?
Your r is a global variable. And these are initialized to zero. The first byte of value is c, the other bytes are zeros.
In contrast, x is a local variable, and those aren't initialied. The first byte of value is c too, but other bytes are like random or garbage, as you call it.