#include<stdio.h>
int main()
{
const char const_cvar1 = 'X';
const char* ptr_to_const_char = &const_cvar1;
// Simply a typecast of "ptr to a const char" to a "ptr to char" disables security !!!
*(char *)ptr_to_const_char = 'S';
printf("\n Value of const char changed from X to : %c \n", const_cvar1);
return 0;
}
Outputs:-
Value of const char changed from X to : S
I wonder if we can never rely on the const qualifier in C ? is it the fact ?
It's C. You can do a lot of things that are stupid, causes undefined behavior, is compiler/platform dependent etc.
casting away the const modifier is one of them. You are able to do so, but you get little guarantees as to what the result will be.
You could even cast it to just about anything, at your own risk.
*(float *)ptr_to_const_char = 2.18;
However, const is not useless.
It provides documentation, a programmer reading code where a pointer is declared const
can assume he can/should not modify what the pointer points to
It can enable the compiler to do further optimizations
Just keep in mind that C does not protect you against yourself or others, it also gives you the ability to not honor the type system.
It is indeed a fact. In fact, the compiler turns off const optimizations (few as there are) the moment it sees you casting away const, treating it like any other variable.
const does not protect a variable. In fact, const does not even mean the variable will never change.
What it means is that you, the programmer, declare that you won't be writing to that part of memory. A memory-mapped input-only pin on a microchip might be represented by a variable qualified const, but it can still change if the voltage on the pin changes. (In fact, it will most likely be declared const volatile, which blew my mind the first time I saw it.) But the const means that you aren't allowed to write to it.
So if you break that promise — that you have no intention of writing to it — well then yes, of course that'll mess things up.
You are programming in C and its always like that. While playing with pointers you need to be careful always.
I believe you want
char * const ptr_to_const_char
which is a constant pointer, not a pointer to a constant.
But that may only work in C++.
Modifying the content of a variable defined as const using such means is clearly UB. Avoid that.
Related
#include <stdio.h>
int main()
{
const int a = 12;
int *p;
p = &a;
*p = 70;
}
Will it work?
It's "undefined behavior," 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 constness 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.
It's undefined behaviour. Proof:
/* program.c */
int main()
{
const int a = 12;
int* p;
p = &a;
*p = 70;
printf("%d\n", a);
return 0;
}
gcc program.c
and run it. Output will be 70 (gcc 4.3)
Then compile it like this:
gcc -O2 program.c
and run it. The output will be 12. When it does optimisation, the compiler presumably loads 12 into a register and doesn't bother to load it again when it needs to access a for the printf because it "knows" that a can't change.
Modifying a const qualified object through a pointer invokes undefined behaviour, and such is the result. It may be something you'd expect from a particular implementation, e.g. the previous value unchanged, if it has been placed in .text, etc.
It does indeed work with gcc. It didn't like it though:
test.c:6: warning: assignment discards qualifiers from pointer target type
But the value did change when executed. I won't point out the obvious no-no...
yes, you can make it done by using such code. but the code do not apply when when a is global (a gcc-compiled program gave me segmentation fault.)
generally speaking, in beloved C, you can almost always find someway to hack things that are not supposed to be changed or exposed. const here being a example.
But thinking about the poor guy(maybe myself after 6 months) maintains our code, I often choose not do so.
Here the type of pointer p is int*, which is being assigned the value of type const int* (&a => address of a const int variable).
Implicit cast eliminates the constness, though gcc throws a warning (please note this largely depends on the implementation).
Since the pointer is not declared as a const, value can be changed using such pointer.
if the pointer would be declared as const int* p = &a, you won't be able to do *p = 70.
This code contains a constraint violation:
const int a = 12;
int *p;
p = &a;
The constraint violated is C11 6.5.16.1/1 "Simple assignment"; if both operands are pointers then the type pointed to by the left must have all the qualifiers of the type pointed to by the right. (And the types, sans qualifiers, must be compatible).
So the constraint is violated because &a has type const int *, which has const as a qualifier; but that qualifier does not appear in the type of p which is int *.
The compiler must emit a diagnostic and might not generate an executable. The behaviour of any executable would be completely undefined, since the program does not comply with the rules of the language.
You cannot change the value of a constant variable by using a pointer pointing to it. This type of pointer is called as Pointer to a constant.
There is also another concept called Constant Pointer. It means that once a pointer points to a memory location you cannot make it point to the another location.
Bad, BAD idea.
Also, the behavior is platform- and implementation-specific. If you're running on a platform where the constant is stored in non-writable memory, this obviously won't work.
And, why on earth would you want to? Either update the constant in your source, or make it a variable.
The problem with changing the value of const variable is that the compiler will not expect that to happen. Consider this code:
const int a = 12;
int * p = &a;
*p = 70;
printf("%d\n", a);
Why would the compiler read a in the last statement? The compiler knows that a is 12 and since it is const, it will never change. So the optimizer may transform the code above into this:
const int a = 12;
int * p = &a;
*p = 70;
printf("%d\n", 12);
This can lead to strange issues. E.g. the code might work as desired in debug builds without optimization but it will fail in release builds with optimization.
Actually a good optimizer might transform the entire code to this:
printf("%d\n", 12);
As all other code before has no effect in the eye of the compiler. Leaving out code that has no effect will also have no effect on the overall program.
On the other hand, a decent compiler will recognize, that your code is faulty and warn you, since
int * p = &a;
is actually wrong. Correct would be:
const int * p = &a;
as p is not a pointer to int, it is a pointer to const int and when declared like that, the next line will cause a hard compile error.
To get rid of the warning, you have to cast:
int * p = (int *)&a;
And an even better compiler will recognize that this cast breaks the const promise and instruct the optimizer to not treat a as const.
As you can see, the quality, capabilities and settings of the compilerwill decide in the end what behavior you can expect. This implies that the same code may show different behavior on different platforms or when using different compilers on the same platform.
If the C standard had defined a behavior for that case, all compilers would have to implement it and no matter what the standard had defined, it would have been hard to implement, putting a huge burden on everyone who wants to write a compiler. Even if the standard had just said "This is forbidden", all compilers would have to perform complex data flow analysis to enforce this rule. So the standard just doesn't define it. It defines that const values cannot be changed and if you find a way to change them anyway, there is no behavior you can rely on.
Yes, you can change the value of a constant variable.
Try this code:
#include <stdio.h>
int main()
{
const int x=10;
int *p;
p=(int*)&x;
*p=12;
printf("%d",x);
}
#include <stdio.h>
int main()
{
const int a = 12;
int *p;
p = &a;
*p = 70;
}
Will it work?
It's "undefined behavior," 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 constness 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.
It's undefined behaviour. Proof:
/* program.c */
int main()
{
const int a = 12;
int* p;
p = &a;
*p = 70;
printf("%d\n", a);
return 0;
}
gcc program.c
and run it. Output will be 70 (gcc 4.3)
Then compile it like this:
gcc -O2 program.c
and run it. The output will be 12. When it does optimisation, the compiler presumably loads 12 into a register and doesn't bother to load it again when it needs to access a for the printf because it "knows" that a can't change.
Modifying a const qualified object through a pointer invokes undefined behaviour, and such is the result. It may be something you'd expect from a particular implementation, e.g. the previous value unchanged, if it has been placed in .text, etc.
It does indeed work with gcc. It didn't like it though:
test.c:6: warning: assignment discards qualifiers from pointer target type
But the value did change when executed. I won't point out the obvious no-no...
yes, you can make it done by using such code. but the code do not apply when when a is global (a gcc-compiled program gave me segmentation fault.)
generally speaking, in beloved C, you can almost always find someway to hack things that are not supposed to be changed or exposed. const here being a example.
But thinking about the poor guy(maybe myself after 6 months) maintains our code, I often choose not do so.
Here the type of pointer p is int*, which is being assigned the value of type const int* (&a => address of a const int variable).
Implicit cast eliminates the constness, though gcc throws a warning (please note this largely depends on the implementation).
Since the pointer is not declared as a const, value can be changed using such pointer.
if the pointer would be declared as const int* p = &a, you won't be able to do *p = 70.
This code contains a constraint violation:
const int a = 12;
int *p;
p = &a;
The constraint violated is C11 6.5.16.1/1 "Simple assignment"; if both operands are pointers then the type pointed to by the left must have all the qualifiers of the type pointed to by the right. (And the types, sans qualifiers, must be compatible).
So the constraint is violated because &a has type const int *, which has const as a qualifier; but that qualifier does not appear in the type of p which is int *.
The compiler must emit a diagnostic and might not generate an executable. The behaviour of any executable would be completely undefined, since the program does not comply with the rules of the language.
You cannot change the value of a constant variable by using a pointer pointing to it. This type of pointer is called as Pointer to a constant.
There is also another concept called Constant Pointer. It means that once a pointer points to a memory location you cannot make it point to the another location.
Bad, BAD idea.
Also, the behavior is platform- and implementation-specific. If you're running on a platform where the constant is stored in non-writable memory, this obviously won't work.
And, why on earth would you want to? Either update the constant in your source, or make it a variable.
The problem with changing the value of const variable is that the compiler will not expect that to happen. Consider this code:
const int a = 12;
int * p = &a;
*p = 70;
printf("%d\n", a);
Why would the compiler read a in the last statement? The compiler knows that a is 12 and since it is const, it will never change. So the optimizer may transform the code above into this:
const int a = 12;
int * p = &a;
*p = 70;
printf("%d\n", 12);
This can lead to strange issues. E.g. the code might work as desired in debug builds without optimization but it will fail in release builds with optimization.
Actually a good optimizer might transform the entire code to this:
printf("%d\n", 12);
As all other code before has no effect in the eye of the compiler. Leaving out code that has no effect will also have no effect on the overall program.
On the other hand, a decent compiler will recognize, that your code is faulty and warn you, since
int * p = &a;
is actually wrong. Correct would be:
const int * p = &a;
as p is not a pointer to int, it is a pointer to const int and when declared like that, the next line will cause a hard compile error.
To get rid of the warning, you have to cast:
int * p = (int *)&a;
And an even better compiler will recognize that this cast breaks the const promise and instruct the optimizer to not treat a as const.
As you can see, the quality, capabilities and settings of the compilerwill decide in the end what behavior you can expect. This implies that the same code may show different behavior on different platforms or when using different compilers on the same platform.
If the C standard had defined a behavior for that case, all compilers would have to implement it and no matter what the standard had defined, it would have been hard to implement, putting a huge burden on everyone who wants to write a compiler. Even if the standard had just said "This is forbidden", all compilers would have to perform complex data flow analysis to enforce this rule. So the standard just doesn't define it. It defines that const values cannot be changed and if you find a way to change them anyway, there is no behavior you can rely on.
Yes, you can change the value of a constant variable.
Try this code:
#include <stdio.h>
int main()
{
const int x=10;
int *p;
p=(int*)&x;
*p=12;
printf("%d",x);
}
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.
#include <stdio.h>
int main()
{
const int a = 12;
int *p;
p = &a;
*p = 70;
}
Will it work?
It's "undefined behavior," 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 constness 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.
It's undefined behaviour. Proof:
/* program.c */
int main()
{
const int a = 12;
int* p;
p = &a;
*p = 70;
printf("%d\n", a);
return 0;
}
gcc program.c
and run it. Output will be 70 (gcc 4.3)
Then compile it like this:
gcc -O2 program.c
and run it. The output will be 12. When it does optimisation, the compiler presumably loads 12 into a register and doesn't bother to load it again when it needs to access a for the printf because it "knows" that a can't change.
Modifying a const qualified object through a pointer invokes undefined behaviour, and such is the result. It may be something you'd expect from a particular implementation, e.g. the previous value unchanged, if it has been placed in .text, etc.
It does indeed work with gcc. It didn't like it though:
test.c:6: warning: assignment discards qualifiers from pointer target type
But the value did change when executed. I won't point out the obvious no-no...
yes, you can make it done by using such code. but the code do not apply when when a is global (a gcc-compiled program gave me segmentation fault.)
generally speaking, in beloved C, you can almost always find someway to hack things that are not supposed to be changed or exposed. const here being a example.
But thinking about the poor guy(maybe myself after 6 months) maintains our code, I often choose not do so.
Here the type of pointer p is int*, which is being assigned the value of type const int* (&a => address of a const int variable).
Implicit cast eliminates the constness, though gcc throws a warning (please note this largely depends on the implementation).
Since the pointer is not declared as a const, value can be changed using such pointer.
if the pointer would be declared as const int* p = &a, you won't be able to do *p = 70.
This code contains a constraint violation:
const int a = 12;
int *p;
p = &a;
The constraint violated is C11 6.5.16.1/1 "Simple assignment"; if both operands are pointers then the type pointed to by the left must have all the qualifiers of the type pointed to by the right. (And the types, sans qualifiers, must be compatible).
So the constraint is violated because &a has type const int *, which has const as a qualifier; but that qualifier does not appear in the type of p which is int *.
The compiler must emit a diagnostic and might not generate an executable. The behaviour of any executable would be completely undefined, since the program does not comply with the rules of the language.
You cannot change the value of a constant variable by using a pointer pointing to it. This type of pointer is called as Pointer to a constant.
There is also another concept called Constant Pointer. It means that once a pointer points to a memory location you cannot make it point to the another location.
Bad, BAD idea.
Also, the behavior is platform- and implementation-specific. If you're running on a platform where the constant is stored in non-writable memory, this obviously won't work.
And, why on earth would you want to? Either update the constant in your source, or make it a variable.
The problem with changing the value of const variable is that the compiler will not expect that to happen. Consider this code:
const int a = 12;
int * p = &a;
*p = 70;
printf("%d\n", a);
Why would the compiler read a in the last statement? The compiler knows that a is 12 and since it is const, it will never change. So the optimizer may transform the code above into this:
const int a = 12;
int * p = &a;
*p = 70;
printf("%d\n", 12);
This can lead to strange issues. E.g. the code might work as desired in debug builds without optimization but it will fail in release builds with optimization.
Actually a good optimizer might transform the entire code to this:
printf("%d\n", 12);
As all other code before has no effect in the eye of the compiler. Leaving out code that has no effect will also have no effect on the overall program.
On the other hand, a decent compiler will recognize, that your code is faulty and warn you, since
int * p = &a;
is actually wrong. Correct would be:
const int * p = &a;
as p is not a pointer to int, it is a pointer to const int and when declared like that, the next line will cause a hard compile error.
To get rid of the warning, you have to cast:
int * p = (int *)&a;
And an even better compiler will recognize that this cast breaks the const promise and instruct the optimizer to not treat a as const.
As you can see, the quality, capabilities and settings of the compilerwill decide in the end what behavior you can expect. This implies that the same code may show different behavior on different platforms or when using different compilers on the same platform.
If the C standard had defined a behavior for that case, all compilers would have to implement it and no matter what the standard had defined, it would have been hard to implement, putting a huge burden on everyone who wants to write a compiler. Even if the standard had just said "This is forbidden", all compilers would have to perform complex data flow analysis to enforce this rule. So the standard just doesn't define it. It defines that const values cannot be changed and if you find a way to change them anyway, there is no behavior you can rely on.
Yes, you can change the value of a constant variable.
Try this code:
#include <stdio.h>
int main()
{
const int x=10;
int *p;
p=(int*)&x;
*p=12;
printf("%d",x);
}
Our static analysis tool complains about a "useless type qualifier on return type" when we have prototypes in header files such as:
const int foo();
We defined it this way because the function is returning a constant that will never change, thinking that the API seemed clearer with const in place.
I feel like this is similar to explicitly initializing global variables to zero for clarity, even though the C standard already states that all globals will be initialized to zero if not explicitly initialized. At the end of the day, it really doesn't matter. (But the static analysis tool doesn't complain about that.)
My question is, is there any reason that this could cause a problem? Should we ignore the errors generated by the tool, or should we placate the tool at the possible cost of a less clear and consistent API? (It returns other const char* constants that the tool doesn't have a problem with.)
It's usually better for your code to describe as accurately as possible what's going on. You're getting this warning because the const in const int foo(); is basically meaningless. The API only seems clearer if you don't know what the const keyword means. Don't overload meaning like that; static is bad enough as it is, and there's no reason to add the potential for more confusion.
const char * means something different than const int does, which is why your tool doesn't complain about it. The former is a pointer to a constant string, meaning any code calling the function returning that type shouldn't try to modify the contents of the string (it might be in ROM for example). In the latter case, the system has no way to enforce that you not make changes to the returned int, so the qualifier is meaningless. A closer parallel to the return types would be:
const int foo();
char * const foo2();
which will both cause your static analysis to give the warning - adding a const qualifier to a return value is a meaningless operation. It only makes sense when you have a a reference parameter (or return type), like your const char * example.
In fact, I just made a little test program, and GCC even explicitly warns about this problem:
test.c:6: warning: type qualifiers ignored on function return type
So it's not just your static analysis program that's complaining.
You can use a different technique to illustrate your intent without making the tools unhappy.
#define CONST_RETURN
CONST_RETURN int foo();
You don't have a problem with const char * because that's declaring a pointer to constant chars, not a constant pointer.
Ignoring the const for now, foo() returns a value. You can do
int x = foo();
and assign the value returned by foo() to the variable x, in much the same way you can do
int x = 42;
to assign the value 42 to variable x.
But you cannot change the 42 ... or the value returned by foo(). Saying that the value returned from foo() cannot be changed, by applying the const keyword to the type of foo() accomplishes nothing.
Values cannot be const (or restrict, or volatile). Only objects can have type qualifiers.
Contrast with
const char *foo();
In this case, foo() returns a pointer to an object. The object pointed to by the value returned can be qualified const.
The int is returned by copy. It may be a copy of a const, but when it is assigned to something else, that something by virtue of the fact that it was assignable, cannot by definition be a const.
The keyword const has specific semantics within the language, whereas here you are misusing it as essentially a comment. Rather than adding clarity, it rather suggests a misunderstanding of the language semantics.
const int foo() is very different from const char* foo(). const char* foo() returns an array (usually a string) whose content is not allowed to change. Think about the difference between:
const char* a = "Hello World";
and
const int b = 1;
a is still a variable and can be assigned to other strings that can't change whereas b is not a variable. So
const char* foo();
const char* a = "Hello World\n";
a = foo();
is allowed but
const int bar();
const int b = 0;
b = bar();
is not allowed, even with the const declaration of bar().
Yes. I would advise writing code "explicitly", because it makes it clear to anyone (including yourself) when reading the code what you meant. You are writing code for other programmers to read, not to please the whims of the compiler and static analysis tools!
(However, you do have to be careful that any such "unnecessary code" does not cause different code to be generated!)
Some examples of explicit coding improving readability/maintainability:
I place brackets around portions of arithmetic expressions to explicitly specify what I want to happen. This makes it clear to any reader what I meant, and saves me having to worry about (or make ay mistakes with) precedence rules:
int a = b + c * d / e + f; // Hard to read- need to know precedence
int a = b + ((c * d) / e) + f; // Easy to read- clear explicit calculations
In C++, if you override a virtual function, then in the derived class you can declare it without mentioning "virtual" at all. Anyone reading the code can't tell that it's a virtual function, which can be disastrously misleading! However you can safely use the virtual keyword: virtual int MyFunc() and this makes it clear to anyone reading your class header that this method is virtual. (This "C++ syntax bug" is fixed in C# by requiring the use of the "override" keyword in this case - more proof if anyone needed it that missing out the "unnecessary virtual" is a really bad idea)
These are both clear examples where adding "unnecessary" code will make the code more readable and less prone to bugs.