This question already has answers here:
can casting away constness lead to undefined behavior? [duplicate]
(5 answers)
Closed 7 years ago.
#include <stdio.h>
int main(){
const int a = 10;
*(int*)(&a) = 9; // modify a
printf("%d", a);
return 0;
}
When I run this code on Xcode, the output is 10 (not changed)
When I run this code on Visual Studio Community, the output is 9 (changed)
Why?
This program would compile but exhibits undefined behavior and may output 9 or 10 or something else or may crash who knows.
When you say a is const, you promise that you won't try change the value of a directly or indirectly and compiler may make certain assumptions. If you break the promise unexpected things may happen.
Q: why?
Ans: undefined behaviour.
To explain, if you try to modify a const variable value by accessing is through some non-const pointer, it invokes undefined behaviour.
As per C11 standard, chapter 6.7.3, paragraph 6.
If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.
Note: The recommended signature of main() is int main(void).
const keyword is used not to change the value of variable. If its done forcefully results may be unexpected
Related
Suppose we declare a variable
int i = 10;
And we have these 2 statements-
printf("%d",i);
printf("%d",*(&i));
These two statements print the same value, i.e. 10
From my understanding of pointers, not just their output is same, but the above two statements mean exactly the same. They are just two different ways of writing the same statement.
However, I came across an interesting code-
#include <stdio.h>
int main(){
const int i = 10;
int* pt1 = &i;
*pt1 = 20;
printf("%d\n", i);
printf("%d\n", *(&i));
return 0;
}
To my surprise, the result is-
10
20
This suggests that i and *(&i) don't mean the same if i is declared with the const qualifier. Can anyone explain?
The behavior of *pt1 = 20; is not defined by the C standard, because pt1 has been improperly set to point to the const int i. C 2018 6.7.3 says:
If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined…
Because of this, the behavior of the entire program is not defined by the C standard.
In C code with defined behavior, *(&i) is defined to produce the value of i. However, in code with behavior not defined by the C standard, the normal rules that would apply to *(&i) are canceled. It could produce the value that the const i was initialized to, it could produce the value the program attempted to change i to, it could produce some other value, it could cause the program to crash, or it could cause other behavior.
Think of what it means to declare something as const - you're telling the compiler you don't want the value of i to change, and that it should flag any code that has an expression like i = 20.
However, you're going behind the compiler's back and trying to change the value of i indirectly through pt1. The behavior of this action is undefined - the language standard places no requirements on the compiler or the runtime environment to handle this situation in any particular way. The code is erroneous and you should not expect a meaningful result.
One possible explanation (of many) for this result is that the i in the first printf statement was replaced with the constant 10. After all, you promised that the value of i would never change, so the compiler is allowed to make that optimization.
But since you take the address of i, storage must be allocated for it somewhere, and in this case it apparently allocated storage in a writable segment (const does not mean "put this in read-only memory"), so the update through pt1 was successful. The compiler actually evaluates the expression *(&i) to retrieve the current value of i, rather than replacing it with a constant. On a different platform, or in a different program, or in a different build of the same program, you may get a different result.
The moral of this story is "don't do that". Don't attempt to modify a const object through a non-const expression.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
#include<stdio.h>
void main() {
const int convalue=64;
int *point;
point = &convalue;
(*point)++;
printf("address of point is %p address of convalue is %p\n",point,&convalue);
printf("convalue is %d and point is %d\n",convalue,*point);
}
How can i modify the constant variable value
How can i modify the constant variable value
You cannot change the value of a constant1 after initialisation. That's what "constant" means.
You can change the program by removing the const qualifier. Then you can change the value. Or, you can conditionally choose another value during initialisation.
1 Except if the constant is of class type, then you can change mutable members of the object.
void main()
The pogram is ill-formed. main must return int in C++. It may not return void.
point = &convalue;
The pogram is ill-formed. A pointer to const doesn't implicitly convert to pointer to non-const. The type system of the language protects you from making mistakes such as this.
(*point)++;
The behaviour of the program is undefined. Const objects must not be modified. This is a bug. Don't write this in a program.
We can't and should never try to modify the value of a const variable. Also,
Any attempt to modify a const object results in undefined behavior.
Also,
note that undefined behavior means anything can happen including but not limited to program being successfully compiled and giving your expected output. But don't rely on the output of a program that has undefined behavior.
For more reading on undefined behavior you can refer to undefined behavior's documentation which mentions:
there are no restrictions on the behavior of the program.
Mistake 2
There is another mistake(in addition to undefined behavior) in your program(in C++). In particular, you should replace
int *point;//INCORRECT
with
const int *point;//CORRECT, note i have added const here
Mistake 3
You should replace void main() with
int main()
Because void main() is not standard C++ as Bjarne Stroustrup made this quite clear in this article
The definition void main() is not and never has been C++, nor has it even been C.
Simply – you can't. "Constant" is constant.
If you need to, you have to use variable instead.
Anyway, there is one possibility to get what you (maybe) want – preprocessor. Question is a bit strange, so I think you could be satisfied by that.
Using preprocessor you can determine what is the initial value of const. (And more, but that's not this case.) Still you can't modify it after it's initialized, but maybe it will be enough for you. For example:
#include<stdio.h>
void main() {
const int convalue=
#ifdef CLI_PROVIDED
CLI_PROVIDED;
#undef CLI_PROVIDED
#else
64;
#endif
int *point;
point = &convalue;
(*point)++;
printf("address of point is %p address of convalue is %p\n",point,&convalue);
printf("convalue is %d and point is %d\n",convalue,*point);
}
Normal compilation will initialize const with value 64. Compilation with option g++ -DCLI_PROVIDED=123 will modify initial value of const BEFORE compilation (this is just text operation) and then compile it with value 123.
Preprocessor is working with code before compilation.
If you want to (for example) create program for multiple operating systems, it will be useful.
This question already has answers here:
C function defined as int but having no return statement in the body still compiles
(7 answers)
Closed 8 years ago.
#include <stdio.h>
int func()
{
}
int main(void)
{
printf("%d\n",func());
return 0;
}
the function "func()" is of "int" return type but is not returning anything. When the function is called in the print function, why is it giving an output 0? And why does it compile successfully although the function definition does not agree to the function code?
If you enable warnings you will see a diagnostic. Traditionally, C implicitly allowed all functions to return int. The behavior of the return value is undefined, so it is not guaranteed to be 0. The behavior could change on different compilers or on different platforms or with different optimization flags or even just by adding or removing other unrelated code. The reason you are probably seeing 0 is because you are running unoptimized and whatever previous value happens to be in the register or stack position is 0. This is pure chance, and relying on the behavior will ultimately result in bugs in your code.
This question already has answers here:
Const variable changed with pointer in C
(5 answers)
Closed 9 years ago.
I wrote a C program in gcc and it's giving me very unexpected output. The code is :
#include<stdio.h>
int main(){
const int x=10;
int *p=&x;
*p=11;
printf("%d\n",*p);
printf("%d",x);
printf("\n%u\n",p);
printf("%u", &x);
}
Here output is:
11
10
37814068
37814068
Why do p and &x give the same address(37814068) but different values(5,10)??
Modifying a const variable (directly or through a pointer) invokes undefined behavior. You may not get the same result in another machine.
In the C Standard mofiying a constant is an undefined behaviour. It means that anything could happen it depends on the machine you're running and the compiler your using. In some cases constants are puted on read-only memory and modifying it's value will cause the program to crash.
Exemple of the error generated by the GCC compiler:
error: assignment of read-only location '* p'
*p = 11;
^
This question already has answers here:
Can we change the value of an object defined with const through pointers?
(11 answers)
Closed 5 years ago.
I am able to change the value of const modified variable in gcc but not in other compilers.
I have tried this code on gcc, which updates the value of i and j (11). With an online compiler, I get different values.
#include<stdio.h>
void main() {
const int i=10;
int *j;
j = &i;
(*j)++;
printf("address of j is %p address of i is %p\n",j,&i);
printf("i is %d and j is %d\n",i,*j);
}
Yes, you can do it with a little hack.
#include <stdio.h>
int main(){
const int a = 0;
*(int *)&a = 39;
printf("%d", a);
}
In the above code, a is a const int. With the little hack, you can change the constant value.
Update: Explanation
In the above code, a is defined as a const. For example a has a memory addr 0x01 and therefore &a returns the same. When it is casted with (int *) it becomes another variable referred as a pointer to the const. When it is accessed with * again, the another variable can be accessed without violation of the const policy because it is not the original variable, but the changes are reflected because it is referred as address to the pointer.
This will work on older versions like Borland C++ or Turbo C++, however no one is using it now a days.
It's "undefined behaviour", meaning that based on the standard you can't predict what will happen when you try this. It may do different things depending on the particular machine, compiler, and state of the program.
In this case, what will most often happen is that the answer will be "yes". A variable, const or not, is just a location in memory, and you can break the rules of const and simply overwrite it. (Of course this will cause a severe bug if some other part of the program is depending on its const data being constant!)
However in some cases -- most typically for const static data -- the compiler may put such variables in a read-only region of memory. MSVC, for example, usually puts const static ints in .text segment of the executable, which means that the operating system will throw a protection fault if you try to write to it, and the program will crash.
In some other combination of compiler and machine, something entirely different may happen. The one thing you can predict for sure is that this pattern will annoy whoever has to read your code.
Try this and let me know.
How to modify value of const variable?
No! You shouldn't modify a const variable.
The whole point of having a const variable is to be not able to modify it. If you want a variable which you should be able to modify, simply don't add a const qualifier on it.
Any code which modify's a const forcibly through (pointer)hackery invokes Undefined Behavior.
An Undefined Behavior means that the code is non conforming to the standard specifications laid out by the C standard and hence not a valid code. Such a code can show any behavior and it is allowed to do so.
By defining i as const, you promised not to modify it. The compiler can rely on that promise and assume that it's not modified. When you print the value of i, the compiler can just print 10 rather than loading whatever value is currently stored in i.
Or it can choose to load the value. Or it can cause your program to crash when you try to modify i. The behavior is undefined.
You'll likely see different behavior with gcc depending on the optimization options (-O1, -O3).
Oh, and void main() is incorrect; it should be int main(void). If your textbook tells you to use void main(), you should get a better book.
Take a look at Can we change the value of an object defined with const through pointers?
Long story short, it's an undefined behaviour. It can result dependently on compiler/machine.
You can not modify the value of const variable if you compile this code in gcc it will show
error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
and show undefined behave
The maiin thing is that we can only modify the variable when we can access the address without address we can't do anything. That's the same thing with Register storage class.