my data in the console is displayed in the wrong sequence - c++

Why is my data in the console displayed in the wrong sequence?
I have the following code:
#include <iostream>
template <typename T, typename T2>
T2 printArr(const T* array, int i) {
for (int j = 0; j < i; j++) {
std::cout << array[j] << " ";
}
std::cout << std::endl;
return array[i - 1];
}
int main() {
const int iSize = 3;
int i_arr[iSize] = {23, 45, 78};
std::cout << "Int array: ";
std::cout << "Last element: " << printArr<int, int>(i_arr, iSize) << std::endl;
}
What do I get by compiling it:
Int array: 23 45 78
Last element: 78
What should I get in my opinion:
Int array: Last element: 23 45 78
78
Most likely, I do not understand how the computer that compiles my code thinks.
Here you can see that the result is the same as I described in my question: http://cpp.sh/2lfbcf
And I also try to compile the code in Visual Studio 2019 and the result is identical

Before C++17, given an expression E1 << E2, it is unspecified whether every value computation and side-effect of E1 is sequenced before every value computation and side effect of E2.
See cppreference note 19
In your code, using a standard before C++17, it is unspecified whether the return value of printArr() is calculated (which as a side-effect, streams to std::cout) before or after std::cout << "Last element: ".

Related

Why isn't that C++ const templated vector initialised before being used?

Update: the question is why the code below (MWE) works as it is and not as I would expect it to.
For personal convenience, I created the following templated vector const:
// shorthand for loops, etc.
template <size_t N>
const vector<size_t> range = []() {
vector<size_t> res(N);
for (size_t i = 0; i < N; i++) res[i] = i;
cout << "Created range<" << N << ">: [";
for (auto x: res) cout << x << ' ';
cout << ']' << endl;
return res;
}();
So that further, I can write more laconic loops like the following:
for (auto i : range<42>) do_something(i);
However, I realised (after some debugging) that it seems to be not guaranteed that all required instantiations of range<N> are initialised before usage! This is rather counter-intuitive so I think if I am doing something wrong.
More precisely, I have the following MWE:
#include <bits/stdc++.h>
using namespace std;
template <size_t N>
const vector<size_t> range = []() {
cout << "Initialising range<" << N << ">" << endl;
vector<size_t> result(N);
for (size_t i = 0; i < N; i++) result[i] = i;
return result;
}();
template <size_t K>
class Data {
private:
size_t m_code;
public:
size_t get_code() const { return m_code; }
constexpr static size_t cardinality = K + 1;
explicit Data(size_t code);
const static vector<Data> elems;
};
template <size_t K>
const vector<Data<K>> Data<K>::elems = []() {
cout << "Creating Data elements for K=" << K << endl;
vector<Data<K>> xs;
for (size_t i : range<Data<K>::cardinality>) xs.push_back(Data<K>(i));
return xs;
}();
template <size_t K>
Data<K>::Data(size_t code) {
m_code = code;
cout << "At the moment, range<" << K << "> is [";
for (auto k : range<K>)
cout << k << ' '; // <<< Shouldn't range<K> be already initialised here?..
cout << "] (len=" << range<K>.size() << ")" << endl;
}
int main() {
cout << ">>> Inside main()" << endl;
constexpr size_t K = 2;
cout << "Data elements:" << endl;
for (const auto &X : Data<K>::elems) {
cout << "Element Data(" << X.get_code() << ")" << endl;
}
cout << "Now, range<" << K << "> is [";
for (auto k : range<K>) cout << k << ' ';
cout << "] (len=" << range<K>.size() << ")" << endl;
}
This produces the following output:
Initialising range<3>
Creating Data elements for K=2
At the moment, range<2> is [] (len=0)
At the moment, range<2> is [] (len=0)
At the moment, range<2> is [] (len=0)
Initialising range<2>
>>> Inside main()
Data elements:
Element Data(0)
Element Data(1)
Element Data(2)
Now, range<2> is [0 1 ] (len=2)
I don't really understand why it is working as it is. I mean, I would expect a const vector (or any vector!) to be initialised before it is used and thus range<2> to be of length two any time I use it in the code.
The dynamic initialization of non-local static storage duration variables resulting from (non-explicit) template specializations is unordered, i.e. sequenced indeterminately, meaning that the order in which the initializations happen is unspecified. It does not take into account either dependencies between the variables, or order of definition, or order of instantiation.
Therefore your program has undefined behavior, since Data<2>::elems, instantiated from the use in main, has unordered dynamic initialization and uses range<2> and range<3>, both of which also have unordered dynamic initialization. Because it is unspecified whether the former or the latter are initialized first, it is possible that you access range<2> or range<3> before their initializations have begun, causing undefined behavior.
This can be resolved by using std::array instead of std::vector for range and in its initializer (and removing the cout statements in the initializer), so that the initializer becomes a constant expression. Then range<K> will not have dynamic initialization, but constant initialization, which is always performed before any dynamic initialization, i.e. before Data<K>::elems will use it.
In addition you should then declare range as constexpr to make sure that the initializer is indeed a constant expression. Otherwise you might still get dynamic initialization and the undefined behavior without warning, for example when you make a change that accidentally causes the initializer not to be a constant expression anymore.

Is this a bug in std::gcd?

I've come across this behavior of std::gcd that I found unexpected:
#include <iostream>
#include <numeric>
int main()
{
int a = -120;
unsigned b = 10;
//both a and b are representable in type C
using C = std::common_type<decltype(a), decltype(b)>::type;
C ca = std::abs(a);
C cb = b;
std::cout << a << ' ' << ca << '\n';
std::cout << b << ' ' << cb << '\n';
//first one should equal second one, but doesn't
std::cout << std::gcd(a, b) << std::endl;
std::cout << std::gcd(std::abs(a), b) << std::endl;
}
Run on compiler explorer
According to cppreference both calls to std::gcd should yield 10, as all preconditions are satisfied.
In particular, it is only required that the absolute values of both operands are representable in their common type:
If either |m| or |n| is not representable as a value of type std::common_type_t<M, N>, the behavior is undefined.
Yet the first call returns 2.
Am I missing something here?
Both gcc and clang behave this way.
Looks like a bug in libstc++. If you add -stdlib=libc++ to the CE command line, you'll get:
-120 120
10 10
10
10

How reinterpret_cast works for flattening a std::vector?

I would like to represent a std::vector of a structure containing several integers as a "flatten" vector of integers, without copying the data.
I tried something with a reinterpret_cast as shown below:
#include <vector>
#include <iostream>
struct Tuple
{
int a, b, c;
};
int main()
{
// init
std::vector<Tuple> vec1(5);
for(size_t i=0; i<vec1.size(); ++i)
{
vec1[i].a = 3 * i + 0;
vec1[i].b = 3 * i + 1;
vec1[i].c = 3 * i + 2;
}
// flattening
std::vector<int>* vec2 = reinterpret_cast<std::vector<int>*>(&vec1);
// print
std::cout << "vec1 (" << vec1.size() << ") : ";
for(size_t i=0; i<vec1.size(); ++i)
{
std::cout << vec1.at(i).a << " " << vec1.at(i).b << " " << vec1.at(i).c << " ";
}
std::cout << std::endl;
std::cout << "vec2 (" << vec2->size() << ") : ";
for (size_t j = 0; j < vec2->size(); ++j)
{
std::cout << vec2->at(j) << " ";
}
std::cout << std::endl;
return 0;
}
which works well since the output is:
vec1 (5) : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
vec2 (15) : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
My questions are :
Is this behavior compiler dependent? (I am using g++ 6.3.0)
How vec2 knows that the size of the vector is 15 and not 5?
Is their any other solution avoiding the use of reinterpret_cast? (If I "accidentally" add a double member to Tuple, the resulting issue could be hard to track...)
If vec1 has a specific allocator: std::vector<Tuple,A<Tuple>>, what should be the type of vec2? std::vector<int> or std::vector<int,A<int>> or std::vector<int,A<Tuple>>?
You can't legally reinterpret_cast the entire vector to a different type of vector. But you can legally cast a pointer to struct to a pointer to the first element of that struct. So this works:
std::vector<Tuple> vec1(5);
int* vec2 = &vec1.front().a;
size_t vec2_size = vec1.size() * sizeof(vec1[0]) / sizeof(vec2[0]);
for (size_t j = 0; j < vec2_size; ++j)
{
std::cout << vec2[j] << " ";
}
You need to make sure there's no padding in Tuple, so:
static_assert(sizeof(Tuple) == 3 * sizeof(int), "Tuple must be 3 ints");
To answer your bulleted questions:
Is this behavior compiler dependent?
Your code was illegal.
How vec2 knows that the size of the vector is 15 and not 5?
You got lucky, your code was illegal.
Is their any other solution avoiding the use of reinterpret_cast?
See above.
If vec1 has a specific allocator: std::vector>, what should be the type of vec2?
Same as above, int*.

Non-trivial example of undefined behavior with const_cast

The following code is, as far as I understand it, undefined behavior according to the c++ standard (section 7.1.5.1.4 [dcl.type.cv]/4 in particular).
#include <iostream>
struct F;
F* g;
struct F {
F() : val(5)
{
g = this;
}
int val;
};
const F f;
int main() {
g->val = 8;
std::cout << f.val << std::endl;
}
However, this prints '8' with every compiler and optimization setting I have tried.
Question: Is there an example that will exhibit unexpected results with this type of "implicit const_cast"?
I am hoping for something as spectacular as the results of
#include <iostream>
int main() {
for (int i = 0; i <=4; ++i)
std::cout << i * 1000000000 << std::endl;
}
on, e.g., gcc 4.8.5 with -O2
EDIT: the relevant section from the standard
7.1.5.1.4: Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime
(3.8) results in undefined behavior.
In reply to the comment suggesting a duplicate; it is not a duplicate because I am asking for an example where "unexpected" results occur.
Not as spectacular:
f.h (guards omitted):
struct F;
extern F* g;
struct F {
F() : val(5)
{
g = this;
}
int val;
};
extern const F f;
void h();
TU1:
#include "f.h"
// definitions
F* g;
const F f;
void h() {}
TU2:
#include "f.h"
#include <iostream>
int main() {
h(); // ensure that globals have been initialized
int val = f.val;
g->val = 8;
std::cout << (f.val == val) << '\n';
}
Prints 1 when compiled with g++ -O2, and 0 when compiled with -O0.
The main case of "undefined" behavior would be that typically, if someone sees const, they will assume that it does not change. So, const_cast intentionally does something that many libraries and programs would either not expect to be done or consider as explicit undefined behavior. It's important to remember that not all undefined behavior comes from the standard alone, even if that is the typical usage of the term.
That said, I was able to locate a place in the standard library where such thinking can be applied to do something I believe would more narrowly be considered undefined behavior: generating an std::map with "duplicate keys":
#include "iostream"
#include "map"
int main( )
{
std::map< int, int > aMap;
aMap[ 10 ] = 1;
aMap[ 20 ] = 2;
*const_cast< int* >( &aMap.find( 10 )->first ) = 20;
std::cout << "Iteration:" << std::endl;
for( std::map< int,int >::iterator i = aMap.begin(); i != aMap.end(); ++i )
std::cout << i->first << " : " << i->second << std::endl;
std::cout << std::endl << "Subscript Access:" << std::endl;
std::cout << "aMap[ 10 ]" << " : " << aMap[ 10 ] << std::endl;
std::cout << "aMap[ 20 ]" << " : " << aMap[ 20 ] << std::endl;
std::cout << std::endl << "Iteration:" << std::endl;
for( std::map< int,int >::iterator i = aMap.begin(); i != aMap.end(); ++i )
std::cout << i->first << " : " << i->second << std::endl;
}
The output is:
Iteration:
20 : 1
20 : 2
Subscript Access:
aMap[ 10 ] : 0
aMap[ 20 ] : 1
Iteration:
10 : 0
20 : 1
20 : 2
Built with g++.exe (Rev5, Built by MSYS2 project) 5.3.0.
Obviously, there is a mismatch between the access keys and the key values in the stored pairs. It also seems that the 20:2 pair is not accessible except via iteration.
My guess is that this is happening because map is implemented as a tree. Changing the value leaves it where it initially was (where 10 would go), so it does not overwrite the other 20 key. At the same time, adding an actual 10 does not overwrite the old 10 because on checking the key value, it's not actually the same
I do not have a standard to look at right now, but I would expect this violates the definition of map on a few levels.
It might also lead to worse behavior, but with my compiler/OS combo I was unable to get it to do anything more extreme, like crash.

c++ (OpenBSD 5.8 amd64), outputting uint64_t as a real number

Trying to understand why I get the following output from my program:
$ ./chartouintest
UInts: 153 97 67 49 139 0 3 129
Hexes: 99 61 43 31 8b 00 03 81
uint64 val: 8103008b31436199
$
I am trying to output just the actual UInt64 numerical value, but can't seem to do it (the output is not right)
here is the code:
#include <iostream>
#include <iomanip>
#include <stdlib.h>
union bytes {
unsigned char c[8];
uint64_t l;
} memobj;
int main() {
//fill with random bytes
for(unsigned int i=0; i < sizeof(memobj.c); ++i) { memobj.c[i] = (unsigned char)rand();}
//see values of all elements as unsigned int8's and hex vals
std::cout << "UInts: ";
for (int x=0; x < sizeof(memobj.c); ++x) { std::cout << (unsigned int)memobj.c[x] << " "; }
std::cout << std::endl;
std::cout << "Hexes: ";
for (int x=0; x < sizeof(memobj.c); ++x) { std::cout << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)memobj.c[x] << " "; }
std::cout << std::endl;
std::cout << "uint64 val: " << memobj.l << std::endl;
}
what am i doing wrong???
thanks in advance for the help!
J
Writing one member of a union and reading another is undefined behavior (with exceptions, but in this case it's UB).
You shouldn't expect anything. The compiler can do WTF it wants with your code, for instance giving a nice "expected" result in debug mode and garbage or crashing in release mode. Of course another compiler might play another trick. You'll never know for sure, so why bother ?
Why not doing it the right way ? memcpy perhaps ?
EDIT:
To really answer the question, a note about std::cout : the std::hex sets the stream to an hexadecimal representation, that's why the final "uint64 val: " display is in hex base (and not in decimal as the OP expects). Other than that, nothing is wrong with the output, despite the UB threat.