Code:
#include <iostream>
int main() {
int a = 137;
const int &b = a;
std::cout << a << " " << b << std::endl; // prints 137 137
a++;
std::cout << a << " " << b << std::endl; // prints 138 138
}
The value of variable b becomes 138 after a++ statement, although it's declared as const Shouldn't this be not allowed? how to make sure this won't happen? or at least get a warning for doing that.
I am using GNU GCC Compiler
Shouldn't this be not allowed?
It's fine. Your code only prevents the b reference from changing the value, but the original variable a doesn't have such a restriction, so it can be freely changed.
Related
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
I am just playing around to see where my current understanding of C++ behaviour ends. I wrote the following code, and got some very unexpected results.
#include <iostream>
#include <cstddef>
using namespace std;
int main()
{
const char c = 'A';
cout << c << endl;
size_t l = (size_t)(&c);
char* d = (char*)l;
*d = 'B';
cout << (size_t)d << " " << (size_t)&c << endl;
cout << *d << " " << c << endl;
}
The first line outputs 'A', as expected. On the second line, the two addresses are the same. However, the third line outputs "B A".
Obviously this is terrible code, but why didn't the value of c change (or why didn't it fail to compile?) In other words, if they both have the same address, why don't they have the same value?
My system is GCC 4.8.1 64-bit on MS Windows 7, x86, if it matters.
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.
Why after using strdup(value) (int)value returns you different output than before?
How to get the same output?
My short example went bad, please use the long one:
Here the full code for tests:
#include <stdio.h>
#include <iostream>
int main()
{
//The First Part
char *c = "ARD-642564";
char *ca = "ARD-642564";
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are equal
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
//The Second Part
c = strdup("ARD-642564");
ca = strdup("ARD-642564");
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are NOT equal Why?
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
int x;
std::cin >> x;
}
Because an array decays to a pointer in your case, you are printing a pointer (ie, on non-exotic computers, a memory address). There is no guarantee that a pointer fits in an int.
In the first part of your code, c and ca don't have to be equal. Your compiler performs a sort of memory optimization (see here for a full answer).
In the second part, strdup allocates dynamically a string twice, such that the returned pointers are not equal. The compiler does not optimize these calls because he does not seem to control the definition of strdup.
In both cases, c and ca may not be equal.
"The strdup() function shall return a pointer to a new string, which is a duplicate of the string pointed to by s1." source
So it's quite understandable that the pointers differ.
EDIT:
Though badly formatted this Question had a nice catch.So, I am editing this to retain this in a better format for future visitors who stumble across this question.
In the code sample below can someone please explain Why is the size of class different than expected after memcpy? What is the reason?
Here is the online demo on Ideone.
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;
class A
{
public:
int a;
virtual void f1() { cout <<"inside a::f1\n"; }
A() { a = 1; }
};
class B
{
public:
int b;
virtual void f2() { cout <<"inside b::f2\n"; }
virtual void f5() { cout <<"inside b::f5\n"; }
B() { b = 2; }
};
class C : public A, public B
{
public:
int c;
void f1() { cout <<"inside c::f1\n"; }
void f2() { cout <<"inside c::f2\n"; }
virtual void f3() { cout <<"inside c::f3\n"; }
virtual void f4() { cout <<"inside c::f4\n"; }
C() { c = 3; }
};
int fun()
{
int a = 1;
return a * 2;
}
int main()
{
C c;
C c2;
int (*g)() = &fun;
void (A::*g1)() = &A::f1;
void (C::*g2)();
g2 = &C::f1;
(c.*g2)();
printf("%p\n",g2);
cout << sizeof(g2) << endl;
g2 = &C::f2;
(c.*g2)();
printf("%p\n", g2);
// Why is the output 1 here in g++ or visual C++?
cout << g2;
// Why is the sizeof returning 8? Please explain.
cout << sizeof(g2) << endl;
g2 = &C::f1;
std::vector<unsigned char> a_vec(sizeof(g2));
memcpy(&a_vec[0], &g2, sizeof(g2));
for(size_t i = 0; i < sizeof(g2); ++i)
{
cout << hex << static_cast<unsigned>(a_vec[i]) << " ";
}
cout << endl;
g2 = &C::f2;
std::vector<unsigned char> a_vec1(sizeof(g2));
memcpy(&a_vec1[0], &g2, sizeof(g2));
for(size_t i = 0; i < sizeof(g2); ++i)
{
cout << hex << static_cast<unsigned>(a_vec1[i]) << " ";
}
cout << endl;
cout << sizeof(g) <<endl;
cout << sizeof(g1) <<endl;
cout << sizeof(g2) <<endl;
// Why is sizeof(C) printing 14 and not 20 in visual C++?
// If yes why is this so ?
cout << sizeof(C) << endl;
cout << sizeof(c2) << endl;
cout << (&c) << endl;
cout << c.a << endl;
cout << c.b << endl;
cout << c.c << endl;
return 0;
}
From the above code sample the Output I get is:
inside c::f1
0x1
8
inside c::f2
0x5
18
1 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0
4
8
8
14
14
0xbffe375c
1
2
3
Following are my Questions:
Why is the output 1 here in g++ or visual C++?
cout << g2;
Why is the sizeof returning 8? Please explain.
cout << sizeof(g2) << endl;
Why is sizeof(C) printing 14 and not 20 in visual C++? If yes why is this so?
cout << sizeof(C) << endl;
Why is the sizeof returning 8. Please explain?
cout <<sizeof(g2)<<endl;
returns 8 because g2 is a pointer and size of an pointer on your enviornment is 8.
Why is the output 1 here in g++ or visual C++?
cout << g2;
The << operator does not have an overloaded version which accepts a pointer. So the pointer gets converted to a bool type, with a value 1, and cout prints it.
The C++ Standard allows this:
C++03 Standard 4.12 Boolean conversions
1 An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool.
Why is sizeof(C) printing 14 and not 20 in visual C++.
cout<<sizeof(C)<<endl;
It displays the size of C correctly just in hexadecimal(14 in hex == 20 in decimal). This is because you used the hex I/O manippulator to print an address before.
cout<<dec<<sizeof(C)<<endl;
will set the I/O manipulator to decimal mode again and it will output 20 as you expect.
A word about printf and type safety:
printf is not type safe.When using printf it is the users responsibility to pass the proper formart descriptor and data type to it. If there is a mismatch then an Undefined Behavior will occur. An Undefined behavior means that the program might crash or show any weird behavior.
printf( "%p\n", g2 );
Is an example of Undefined Behavior, there is a mismatch in the format descriptor and the data type. Note that the compiler does complain about this and you should always look out and check such warnings emitted by the compiler.
warning: format ‘%p’ expects type ‘void*’, but argument 2 has type ‘void (C::*)()’
The results of sizeof for a given type never change. (At least for a
conforming C++ program. g++, I believe, supports VLAs in C++, as an
extension, and the sizeof an object containing a VLA might change.)
With regards to your explicit questions:
printf( "%p\n", g2 );
is undefined behavior. You're passing a pointer to member to an output
formatter which requires a void*. (g++ will warn about this, I
believe, at least with certain options.) You might get just about
anything (including a program crash). Pointers to members are not
void*, and can't be converted to void*.
cout << g2;
I can't believe that this compiles.
cout << sizeof(g2) << endl;
sizeof(g2) returns 8 because this is the size of a pointer to member
on your system.
cout << sizeof(C) << endl;
Prints 14 because this is the size in hexadecimal of an object of type
C on your system. In other words, sizeof(C) is 20. Since you've
set output for hex, and never reset it, the output is hexadecimal.