Can we cast a const int into an int in C++ without declaring a new variable?
This option is available in VS but how can it be used in other compilers such as Xcode, code blocks, etc?
const int a = 5 ;
int (a) ++ ;
a is const. You can't legally remove the constness to mutate the variable in any compiler. What you're seeing in VS is that it's letting you create an unnamed temporary and incrementing THAT.
TL;DR: You can change the value of a const variable but you can't guarantee your code will behave as though you did.
There is, of course, a way to do it, but first lets make sure you understand what you're asking to do:
const int a = 5;
This tells the compiler that there is a value, 5, which you want to refer to as "a", for example so you can do:
const int MaxNameLen = 5;
char name[MaxNameLen + 1];
or
const float pi = 3.14;
return pi * radius;
Compiled without optimization, this will probably produce code which injects a variable like any other and uses it as you would expect.
But by calling the variable "const" you've signed a contract with the compiler: Behave as tho this value does not change. So you can do, for example:
int a = 5;
*(static_cast<int*>(&a))++;
But as far as the compiler is concerned, a did not change. It is free to carry on behaving as tho it didn't. So if it loaded it into a register, if it sized something based on it, it is free to just go ahead and assume it can use the value "5" wherever it sees "a". For example:
#include <iostream>
using namespace std;
int main()
{
const int a = 5;
(*const_cast<int*>(&a))++;
std::cout << "a = " << a << std::endl;
}
might print 5 or it might print 6, depends on which compiler, which settings and the context of the code. Variable "a" has an address but you told the compiler it wouldn't change, so it may already have pushed it onto the stack or loaded it into a register.
Where this is going to hurt you worst is in highly optimized because the compiler is going to produce instructions and ordering based on your promise that "a" does not change.
Related
This question already has answers here:
Sell me const-correctness
(16 answers)
Closed 2 years ago.
What is the point of using the keyword const? for example when making a game, one of the first things to do is to set the width and height of it. And most of the time you'll use for example:
const int Width
and
const int height
Now I know that you should do it like that because the width and height of the screen will not change throughout the game, but what is the point of doing so ? you can do the same thing without using const and it will work just fine.
That was just an example. so what I'm confused about right now is:
What is the point of using the const keyword anywhere if you won't change the variable anyway?
Non-exhaustive list of reasons:
Software Engineering (SWE). SWE is not just programming, but programming with other people and over time.
const allows to explicitly express an invariant, which lets you and others reason about the code. As the program becomes bigger, these invariants cannot be just memorized. That's why encoding them in the programming language helps.
Optimization opportunities.
With the knowledge that certain values will not change, the compiler can make optimizations that would not be possible otherwise. To take this to the max, constexpr means that a value will be known at compile time, not just at run-time. This becomes even more important in potentially multi-threading contexts.
Example:
What kind of optimization does const offer in C/C++?
I leave out whole program analysis which would require a much longer answer and almost certainly is not applicable to generic C++ programs. But whole-program-analysis will allow reasoning of the analyzer or compiler about constness of variables as they get passed between functions, translation units and libraries.
Without const, you have to remember to not change the variable. The larger your program becomes, the harder it gets.
It also has some other useful effects:
const int a = 10;
int b[a]; // Doesn't work if `a` is not `const`.
// ...
void foo(const int &a) {};
void bar()
{
foo(42); // Doesn't work if the parameter is a non-const reference.
}
Having something declared const, compared to a value set with #define for instance, allows you to declare something that the compiler will never let you alter, but that will still keep all of the other properties of a regular variable.
In particular, it will keep a certain place in memory and a pointer on it can be obtained with « & », keeping all read-only routines that use to work on regular object compatible with it.
It's especially useful when your constant object is not a simple native type variable, but rather a complicated object spawned from a class and that still need to be initialized through a constructor.
Also remember that const is a type qualifier, than can apply not only on variable declarations, but also on arguments of a function prototype. In this particular case, this will enable your function to accept both constant or variable arguments.
Such a constant argument could be, for example, a double-quoted "string", which is const char *-typed, because the string is directly part of the code itself and defined at compilation type. Without a const qualifier, nothing could prevent your function from trying to write in it, nor warn the programmer that it's forbidden.
To stay with your example, suppose I write a game library that has a
struct game {
int width;
int height;
int area;
game(int w, int h) : width(w),height(h),area(w*h) {}
};
Now you use my library and because I did not write any documentation (evil me) you just start writing code and try what you can do with that class. You write code
#include <iostream>
int main() {
game g{3,5};
g.width = 12;
std::cout << g.width << " * " << g.height << " == " << g.area;
}
and get output:
12 * 5 == 15
You will complain that the code I wrote is broken because you get non-sense results when you use it. If however I had used const for things you are not supposed to modify:
struct game {
const int width;
const int height;
const int area;
game(int w, int h) : width(w),height(h),area(w*h) {}
};
Then you would get a nice error message that tells you that you tried to modify something that you are not supposed to modify:
prog.cc: In function 'int main()':
prog.cc:11:15: error: assignment of read-only member 'game::width'
g.width = 12;
Once you fixed your code to
#include <iostream>
int main() {
game g{3,5};
std::cout << g.width << " * " << g.height << " == " << g.area;
}
All const could be removed and the output would not change. However this is not always the case. For example member functions can have const and non-const overloads that can do different things depending on whether the method is called on a const or on a non-const object:
#include <iostream>
struct foo {
void sayHello() const {
std::cout << "I am a const object\n";
}
void sayHello() {
std::cout << "I am a non-const object\n";
}
};
int main() {
const foo f;
f.sayHello();
foo g;
g.sayHello();
}
output:
I am a const object
I am a non-const object
Conclusion:
const is mainly to ensure correctnes and to avoid mistakes. const can also be used to make const objects behave differently than non const objects. There is more to it and details you can read up eg here.
const is for a constant variable, that it means nobody should change it, or maybe for const T & passing non-trivial type as parameter, or maybe for making a pointer constant, or for value pointed from the pointer (const *P *variable)
Q1:
I have recently read book C++ Primer, when I read follow:
To substitute the value for the variable, the compiler has to see the variable’s initializer. When we split a program into multiple files, every file that uses the const must have access to its initializer. In order to see the initializer, the variable must be defined in every file that wants to use the variable’s value.
I have a question: when I use a variable defined in other file, I just use extern to declare is enough, why should I must have access to its initializer, so I have done a test:
in main.cpp, I write below:
#include <iostream>
using namespace std;
extern int test;
int main()
{
cout << test << endl;
return 0;
}
in test.cpp, I write below:
int test = 100;
and by the way, these two files are added in the same projects, or it will not build successful.
When I run them, it print
100
like I expect. But in main.cpp, I don't need to define something like int test = 100 like book said. I don't know who is right.
Q2:
int i = 43;
const int &r = i;
i = 1; //when i changed, r alse changed
I have tested in gcc 4.7 and visual studio 2013, they both get same result,
r changed. Then, what's the point of const? Shouldn't r always be 43?
I think the quote from the book means something like the following
const size_t N = 10;
int main()
{
int a[N];
//...
}
If the constant N is defined in some other module with specifier extern then in the module with main the compiler does not have an access to the value of the constant and as result it is unable to define the array
extern const size_t N;
int main()
{
int a[N]; // error: the value N is unknown
//...
}
By this reason constants have internal linkage that it could be possible to define them in each module where their values are required at compile time.
As for the second question then constant references are used that to prevent modifying the referenced objects using references.
For example if you want that some function would not change your compound object you can declare its parameter as a constant reference to the object.
Also a temporary objects are bound to constant references.
Consider an example
void display_string( const std::string &s )
{
std::cout << s << std::endl;
}
you may call the function using a character array. For example
display_string( "Hello, World" );
The compiler implicitly converts the string literal to a temporary object of type std::string and binds it to the constant reference of the parameter.
If the parameter would not be declared like constant reference as for example
void display_string( std::string &s );
then the compiler would issue an error.
Using a constant reference it is supposed that the client code will not change the referenced object itself.
That is the client code may look at the object but may not touch it by hands.:)
Q1. have access to its initializer means compiler need to known the variable's initializer(definition). You can let compiler achieve that by link main.cpp and test.cpp together. You said that these two files are added in the same projects, so IDE will do that for you.
You can find more on this question.
Q2. Compiler don't allow you to change r's value, because it's a reference to a const variable, but i is an integer variable, so you can change it's value.
When I tried below code I got strange results.I am trying to change value of constant by using the pointers.But when I output the results pointer value and the original variable variable value its giving two different values.Can anyone explain what exactly happens when explicit conversion take place?
int main()
{
int *p ;
const int a = 20;
p=(int *)&a;
*p = *p +10;
cout<<"p is"<<*p<<"\na is"<<a;
}
output:
p is 30
a is 20
Both C and C++ say that any attempt to modify an object declared with the const qualifier results in undefined behavior.
So as a is object is const qualified, the *p = *p +10; statement invokes undefined behavior.
First of - You really shouldn't be doing this. const is a constant, meaning don't change it! :)
Now to explain what happens (I think):
The space on the stack is allocated for both variables, p and a. This is done for a because it has been referenced by an address. If you removed p, you'd effectively remove a as well.
The number 20 is indeed written to the a variable, and modified to 30 via p, which is what is being printed.
The 20 printed is calculated at compile time. Since it is a const, the compiler optimized it away and replaced with 20, as if you did a #define a 20.
Don't Do That.
If you would write this code in C++ with an explicit cast, you would get something like this:
int main()
{
int *p ;
const int a = 20;
p= const_cast<int*>(&a); // the change
*p = *p +10;
cout<<"p is"<<*p<<"\na is"<<a;
}
Now, this code tells a bit more about what's going on: the constant is cast to a non-constant.
If you are writing a compiler, constants are special variables that are allowed to be 'folded' in the const folding phase. Basically this means that the compiler is allowed to change your code into this:
int main()
{
int *p ;
const int a = 20;
p= const_cast<int*>(&a);
*p = *p +10;
cout<<"p is"<<*p<<"\na is" << 20; // const fold
}
Because you're also using &a, you tell the compiler to put the value 20 in a memory location. Combined with the above, you get the exact results you describe.
This is undefined behavior.
A compiler can assume that nothing is going to change the value of a const object. The compiler knows that the value of "a" is 20. You told the compiler that. So, the compiler actually goes ahead and simply compiles the equivalent of
cout << "p is" << *p << "\na is" << 20;
Your compiler should've also given you a big fat warning, about "casting away const-ness", or something along the same lines, when it tried to compile your code.
Although it is defined as undefined behaviour (as everyone else tells you), it could be that your compiler has allocated a storage location (int) for the const int; that is why the *p= *p + 10 works, but may have repaced a in the output statement with the value 20, as it is supposed to be constant.
What is more efficient: Call by pointer or by value? I think it is call by pointer, because passing a pointer to a variable does not use as much memory as creating a copy of a variable. Am I wrong?
main(){
int a, b;
a = 10;
b = 5;
gcf(&a, &b);
return 0;
}
int gcf(int* c, int* d){
int val1=*c;
int val2=*d;
//...
}
In nearly all code, as long as we're dealing with small/simple objects, the overhead of copying the object, vs. passing it as a pointer or reference is pretty small.
Obviously, if we make a std::string with a large chunk of text in it, it will take quite some time to copy it, relative to just passing a reference.
However, the primary objecting ANY TIME when writing code is to focus on correctness. If you have "large" objects, then use const Type &val if the value is not being modified - that way, you can't accidentally modify it. If the object is to be modified, then you NEED to use a reference or pointer to get the updates back to the caller of the function.
It is entirely possible to make code that runs noticeably slower with a reference than with a value. I was once looking into the performance of some code that we were working on, and found a function that looked something like this:
void SomeClass::FindThing(int &thing)
{
for(thing = 0; someVector[thing] != 42; thing++)
;
}
It really looks rather innocent, but since each update of thing means an indirect memory access [at least in the compiler we used, which was certainly not "rubbish"], it was taking quite a lot of time out of the entire process [it was also called twice as much as necessary].
I rewrote it as:
void SomeClass::FindThing(int &thing)
{
for(int i = 0; someVector[i] != 42; i++)
;
thing = i;
}
And the function ran about 4x faster. Taking out the second, unnecessary call, as well, and we ended up with about 30% faster runtime. This was in a "fonts benchmark", and this was one out of a several dozen functions involved in the "draw fonts to screen". It's scary how a simple, innocent looking function can make a BIG difference to performance.
For types smaller than the size of a pointer (e.g. int), passing by value is more efficient.
For types bigger than the size of a pointer (e.g. most struct or class instances), passing by reference is probably more efficient (only "probably" because on top of the cost of passing the parameter, potentially constructing an object, you incur the cost of dereferencing your parameter every time you use it).
More details about passing-by-value vs. passing-by-reference can be found in this question. More details about reference vs. pointer arguments can be found in that question.
In your example of code snippet
main(){
int a, b;
a = 10;
b = 5;
}
int gcf(int* c, int* d){
int rem;
int val1=*c;
int val2=*d;
//...
}
there is no any sense to pass variables a and b to the function indirectly using pointers if you are not going to change them. In this case the code is ineffective because that to get values of *c and *d the compiler will need to generate more instructions.
And you are wrong saying that
passing a pointer to a variable does not use as much memory as
creating a copy of a variable. Am I wrong?
Usually pointers are equal to or even larger than the size of type int. For exaple in a 64-bit system sizeof( int ) can be equal to 4 while sizeof( int * ) can be equal to 8.
There is a sense to pass an object indirectly by pointers (usually in C programs) when the size of the object is much larger than the size of the pointer.
In C++ instead of pointers usually references are used.
For example
#include <iostream>
#include <string>
inline void print_reverse( const std::string &s )
{
std::cout << std::string( s.rbegin(), s.rend() ) << std::endl;
}
int main()
{
std::string s( "Hello World" );
print_reverse( s );
}
Here const std::string &s defined reference to an object of type std::string.
I've been reading about strict aliasing quite a lot lately. The C/C++ standards say that the following code is invalid (undefined behavior to be correct), since the compiler might have the value of a cached somewhere and would not recognize that it needs to update the value when I update b;
float *a;
...
int *b = reinterpret_cast<int*>(a);
*b = 1;
The standard also says that char* can alias anything, so (correct me if I'm wrong) compiler would reload all cached values whenever a write access to a char* variable is made. Thus the following code would be correct:
float *a;
...
char *b = reinterpret_cast<char*>(a);
*b = 1;
But what about the cases when pointers are not involved at all? For example, I have the following code, and GCC throws warnings about strict aliasing at me.
float a = 2.4;
int32_t b = reinterpret_cast<int&>(a);
What I want to do is just to copy raw value of a, so strict aliasing shouldn't apply. Is there a possible problem here, or just GCC is overly cautious about that?
EDIT
I know there's a solution using memcpy, but it results in code that is much less readable, so I would like not to use that solution.
EDIT2
int32_t b = *reinterpret_cast<int*>(&a); also does not work.
SOLVED
This seems to be a bug in GCC.
If you want to copy some memory, you could just tell the compiler to do that:
Edit: added a function for more readable code:
#include <iostream>
using std::cout; using std::endl;
#include <string.h>
template <class T, class U>
T memcpy(const U& source)
{
T temp;
memcpy(&temp, &source, sizeof(temp));
return temp;
}
int main()
{
float f = 4.2;
cout << "f: " << f << endl;
int i = memcpy<int>(f);
cout << "i: " << i << endl;
}
[Code]
[Updated Code]
Edit: As user/GMan correctly pointed out in the comments, a full-featured implementation could check that T and U are PODs. However, given that the name of the function is still memcpy, it might be OK to rely on your developers treating it as having the same constraints as the original memcpy. That's up to your organization. Also, use the size of the destination, not the source. (Thanks, Oli.)
Basically the strict aliasing rules is "it is undefined to access memory with another type than its declared one, excepted as array of characters". So, gcc isn't overcautious.
If this is something you need to do often, you can also just use a union, which IMHO is more readable than casting or memcpy for this specific purpose:
union floatIntUnion {
float a;
int32_t b;
};
int main() {
floatIntUnion fiu;
fiu.a = 2.4;
int32_t &x = fiu.b;
cout << x << endl;
}
I realize that this doesn't really answer your question about strict-aliasing, but I think this method makes the code look cleaner and shows your intent better.
And also realize that even doing the copies correctly, there is no guarantee that the int you get out will correspond to the same float on other platforms, so count any network/file I/O of these floats/ints out if you plan to create a cross-platform project.