Is const really const?

  • Thread starter Rohit kumar Chandel
  • Start date
R

Rohit kumar Chandel

Hi all,

I have a doubt in const keyword. My understanding says that a variable
declared const can not be modified by the module it is defined in. Then
consider the following code segment:
main()
{
const int p =5;
int* pp = &p;
++(*pp);
printf("%d\n",p);
}
To my surprise it increments value of p by one where p has to be a
constant. Please clarify my doubt.

Thanks and regards
Rohit
 
I

Ian Collins

Rohit said:
Hi all,

I have a doubt in const keyword. My understanding says that a variable
declared const can not be modified by the module it is defined in. Then
consider the following code segment:
main()
{
const int p =5;
int* pp = &p;
++(*pp);
printf("%d\n",p);
}
To my surprise it increments value of p by one where p has to be a
constant. Please clarify my doubt.
If you didn't get at least three warnings for the above, turn your
compiler's warning level up so it tells you what is wrong with your code.

Yes C will let you get away with what you have written, but the result
is undefined behaviour.
 
K

Keith Thompson

Rohit kumar Chandel said:
I have a doubt in const keyword. My understanding says that a variable
declared const can not be modified by the module it is defined in. Then
consider the following code segment:
main()
{
const int p =5;
int* pp = &p;
++(*pp);
printf("%d\n",p);
}
To my surprise it increments value of p by one where p has to be a
constant. Please clarify my doubt.

In most of the English-speaking world outside India, "doubt" is not
merely a synomym for "question. In international forums like this
one, you'd have a better chance of being understood if you write "I
have a question about the const keyword".

In your program above, the declaration
int *pp = &p;
violates a constraint. For one compiler, it produces a warning
message:
warning: initialization discards qualifiers from pointer target type

You can't legally assign the address of a const object to a non-const
pointer object. This rule exists precisly to avoid the problem you're
seeing. Once the compiler diagnoses the problem, though, it's allowed
to continue to compile the program.

Increase the warning level of your compiler, and pay attention to any
warning messages it produces.

If you really want to modify a const object then ... well, first of
all, you shouldn't try to modify a const object; if you need to modify
it, it shouldn't have been declared const in the first place.

But here's a way to do what you're trying to do:

#include <stdio.h> /* required for printf */
int main(void)
{
const int p = 5;
int *pp = (int*)&p; /* The cast suppresses the warning */
++(*pp);
printf("%d\n", p);
return 0;
}

The cast in effect tells the compiler that you know what you're doing.
This is almost always a bad idea, and the behavior of the program is
undefined. A compiler could *assume* that p is never modified (since
you promised not to modify it) and print 5 even if you've managed to
store the value 6 in its memory location.
 
J

Jean-Marc Bourguet

Rohit kumar Chandel said:
I have a doubt in const keyword. My understanding says that a variable
declared const can not be modified by the module it is defined in. Then
consider the following code segment:
main()
{
const int p =5;
int* pp = &p;
++(*pp);
printf("%d\n",p);
}
To my surprise it increments value of p by one where p has to be a
constant. Please clarify my doubt.

The line

int* pp = &p;

should have been diagnostized by the compiler.

Yours,
 
R

Rohit kumar Chandel

Keith Thompson said:
In most of the English-speaking world outside India, "doubt" is not
merely a synomym for "question. In international forums like this
one, you'd have a better chance of being understood if you write "I
have a question about the const keyword".

In your program above, the declaration
int *pp = &p;
violates a constraint. For one compiler, it produces a warning
message:
warning: initialization discards qualifiers from pointer target type

You can't legally assign the address of a const object to a non-const
pointer object. This rule exists precisly to avoid the problem you're
seeing. Once the compiler diagnoses the problem, though, it's allowed
to continue to compile the program.

Increase the warning level of your compiler, and pay attention to any
warning messages it produces.

If you really want to modify a const object then ... well, first of
all, you shouldn't try to modify a const object; if you need to modify
it, it shouldn't have been declared const in the first place.

But here's a way to do what you're trying to do:

#include <stdio.h> /* required for printf */
int main(void)
{
const int p = 5;
int *pp = (int*)&p; /* The cast suppresses the warning */
++(*pp);
printf("%d\n", p);
return 0;
}

The cast in effect tells the compiler that you know what you're doing.
This is almost always a bad idea, and the behavior of the program is
undefined. A compiler could *assume* that p is never modified (since
you promised not to modify it) and print 5 even if you've managed to
store the value 6 in its memory location.
Thanks Mr Thompson for providing insight and at the same time correcting
english grammer as well :)
I have one more question on const keyword. I have gone through lot of
reading material to find its answer, but in vain. Most of these materials
say that a variable declared to be const can not be modified in the module
in which it is defined. From this I assume it can be modified by code
outside the module it is defined in. But what is a module here. Is it the
function, file or anything else.Does it mean that there is a normal way to
do it (apart from supressing warnings by using explicit cast). Please
clarify it with example.
 
I

Ian Collins

Rohit said:
I have one more question on const keyword. I have gone through lot of
reading material to find its answer, but in vain. Most of these materials
say that a variable declared to be const can not be modified in the module
in which it is defined. From this I assume it can be modified by code
outside the module it is defined in. But what is a module here. Is it the
function, file or anything else.Does it mean that there is a normal way to
do it (apart from supressing warnings by using explicit cast). Please
clarify it with example.
You misunderstand. Modifying anything declared const results in
undefined behaviour.
 
K

Keith Thompson

Rohit kumar Chandel said:
I have one more question on const keyword. I have gone through lot of
reading material to find its answer, but in vain. Most of these materials
say that a variable declared to be const can not be modified in the module
in which it is defined. From this I assume it can be modified by code
outside the module it is defined in. But what is a module here. Is it the
function, file or anything else.Does it mean that there is a normal way to
do it (apart from supressing warnings by using explicit cast). Please
clarify it with example.

I don't know where the "in the module in which it is defined" wording
comes from.

If an object is declared as "const", then there is no way to modify
that object without invoking undefined behavior.

I suppose you could define an object as "const" in one translation
unit, and declare it without the "const" in another translation unit,
and the implementation *might* not catch the error, but it's still an
error.
 
S

Sheth Raxit

Thanks Mr Thompson for providing insight and at the same time correcting
english grammer as well :)
I have one more question on const keyword. I have gone through lot of
reading material to find its answer, but in vain. Most of these materials
say that a variable declared to be const can not be modified in the module
in which it is defined. From this I assume it can be modified by code
outside the module it is defined in. But what is a module here. Is it the
function, file or anything else.Does it mean that there is a normal way to
do it (apart from supressing warnings by using explicit cast). Please
use #define :), i hope i am not dragging to wrong direction.
 
J

Jean-Marc Bourguet

Rohit kumar Chandel said:
Thanks Mr Thompson for providing insight and at the same time correcting
english grammer as well :)
I have one more question on const keyword. I have gone through lot of
reading material to find its answer, but in vain. Most of these materials
say that a variable declared to be const can not be modified in the module
in which it is defined. From this I assume it can be modified by code
outside the module it is defined in. But what is a module here. Is it the
function, file or anything else.Does it mean that there is a normal way to
do it (apart from supressing warnings by using explicit cast). Please
clarify it with example.

An object which has been declared const may not be modified without
undefined behaviour. But you may get const view of non const objects. In
the later case, it is possible that you have two aliases, one const, one
not and then it is possible to modify the object. And I'm pretty sure but
I've not checked -- that you can even cast the const away of a const view
while staying in the defined realm.

void f1(int const* p1, int* p2) {
*p2 = 42;
}

void f2(int const* p1) {
*(int*)p1 = 36;
}

void foo() {
int const i1 = 1;
int i2 = 2;

f1(&i1, (int*)&i1); /* trigger undefined behaviour */
f2(&i1); /* trigger undefined behaviour */
f1(&i2, &i2); /* no undefined behaviour */
f2(&i2); /* probably no undefined behaviour */
}
 
R

Rohit kumar Chandel

Keith Thompson said:
I don't know where the "in the module in which it is defined" wording
comes from.

If an object is declared as "const", then there is no way to modify
that object without invoking undefined behavior.

I suppose you could define an object as "const" in one translation
unit, and declare it without the "const" in another translation unit,
and the implementation *might* not catch the error, but it's still an
error.

--

Here is the cause of my confusion. Thought it'll help you to understand the
problem better. This is from one of training slides. Goes like this:
/* real-time clock (hardware) */
const volatile T_RTC *pRTC = CLOCK_ADRESS;
....
void printTime()
{
printf("%d:%d:%d\n",
pRTC->std,pRTC->min,pRTC->sec);
}
....
void killRTC()
{
pRTC = NULL; /* <- ? */
}
....
??? Is the line in 'killRTC' allowed ???

Explaination:
const volatile T_RTC *pRTC = CLOCK_ADRESS;
The keyword 'const' indicates that the variable must not be changed
by this module (but maybe changed by another module).
Here next variable to the right is '*pRTC',
so '*pRTC' will not be changed by this module,
so the value of the memory where 'pRTC' points to will not be changed.
But the variable 'pRTC' is allowed to change!
So the code on the page before is correct and works.

Best Regards
Rohit
 
J

JimS

Here is the cause of my confusion. Thought it'll help you to understand the
problem better. This is from one of training slides. Goes like this:
/* real-time clock (hardware) */
const volatile T_RTC *pRTC = CLOCK_ADRESS;
...
void printTime()
{
printf("%d:%d:%d\n",
pRTC->std,pRTC->min,pRTC->sec);
}
...
void killRTC()
{
pRTC = NULL; /* <- ? */
}
...
??? Is the line in 'killRTC' allowed ???

Explaination:
const volatile T_RTC *pRTC = CLOCK_ADRESS;
The keyword 'const' indicates that the variable must not be changed
by this module (but maybe changed by another module).
Here next variable to the right is '*pRTC',
so '*pRTC' will not be changed by this module,
so the value of the memory where 'pRTC' points to will not be changed.
But the variable 'pRTC' is allowed to change!
So the code on the page before is correct and works.

Best Regards
Rohit

pRTC is a pointer to a constant, not a constant pointer. So pRTC may
be changed.

Jim
 
J

James Kuyper

Rohit kumar Chandel wrote:
....
Here is the cause of my confusion. Thought it'll help you to understand the
problem better. This is from one of training slides. Goes like this:
/* real-time clock (hardware) */
const volatile T_RTC *pRTC = CLOCK_ADRESS;
...
void printTime()
{
printf("%d:%d:%d\n",
pRTC->std,pRTC->min,pRTC->sec);
}
...
void killRTC()
{
pRTC = NULL; /* <- ? */
}
...
??? Is the line in 'killRTC' allowed ???

Explaination:
const volatile T_RTC *pRTC = CLOCK_ADRESS;
The keyword 'const' indicates that the variable must not be changed
by this module (but maybe changed by another module).


That last line is simply and completely wrong. I'd recommend not
trusting anything you've learned from that training course. Someone who
made that mistake is likely to have made many other mistakes as well.
 
P

pete

Rohit kumar Chandel wrote:
Explaination:
const volatile T_RTC *pRTC = CLOCK_ADRESS;
The keyword 'const' indicates that the variable must not be changed

That's different from what you think it means.

This:
volatile T_RTC *const pRTC = CLOCK_ADRESS;
means the keyword 'const' indicates that pRTC must not be changed.

This:
const volatile T_RTC *pRTC = CLOCK_ADRESS;
means the keyword 'const' indicates that what pRTC points to,
must not be changed.

Take a look at the prototypes for copying functions in string.h

void *memcpy(void *s1, const void *s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);
char *strcpy(char *s1, const char *s2);
char *strncpy(char *s1, const char *s2, size_t n);
char *strcat(char *s1, const char *s2);
char *strncat(char *s1, const char *s2, size_t n);

You'll notice that the second parameter
always points to a const qualified type.
This indicates that the function will not
alter the value of anything that s2 points to.

The guarantee that the function will not
alter the value of anything that s2 points to,
is in the standard description of the library functions;
the presence of the const keyword in those prototypes,
is merely an indication that that is the case.
 
G

Golden California Girls

Rohit said:
I have one more question on const keyword. I have gone through lot of
reading material to find its answer, but in vain. Most of these materials
say that a variable declared to be const can not be modified in the module
in which it is defined. From this I assume it can be modified by code
outside the module it is defined in. But what is a module here. Is it the
function, file or anything else.Does it mean that there is a normal way to
do it (apart from supressing warnings by using explicit cast). Please
clarify it with example.

Not in scope. (You can't modify what doesn't exist.)
 
K

Keith Thompson

Rohit kumar Chandel said:
Here is the cause of my confusion. Thought it'll help you to understand the
problem better. This is from one of training slides. Goes like this:
/* real-time clock (hardware) */
const volatile T_RTC *pRTC = CLOCK_ADRESS;
...
void printTime()
{
printf("%d:%d:%d\n",
pRTC->std,pRTC->min,pRTC->sec);
}
...
void killRTC()
{
pRTC = NULL; /* <- ? */
}
...
??? Is the line in 'killRTC' allowed ???

Certainly; it's not even questionable. pRTC itself is not const. The
object that it *points to* is const (and volatile).

So this:

pRTC = NULL;

is perfectly ok, whereas this:

pRTC->std = 42; /* constraint violation! */

is not, because it attempts to modify a const object.

See if you can find a program called "cdecl". For example:

% cdecl
Type `help' or `?' for help
cdecl> explain const volatile int *obj
declare obj as pointer to const volatile int
cdecl>
Explaination:
const volatile T_RTC *pRTC = CLOCK_ADRESS;
The keyword 'const' indicates that the variable must not be changed
by this module (but maybe changed by another module).

The object that must not be changed (at least not directly) is *pRTC,
not pRTC itself.

Once again, "modules" have nothing to do with it. C doesn't even
define anything called a "module". (Perhaps it's meant to refer to a
translation unit, which roughly means a source file. It's true that,
in some cases, requirements are not enforced as strictly across
translation units as within them, but the requirements are still
there.)

Can you find out just what is meant by a "module"?
Here next variable to the right is '*pRTC',
so '*pRTC' will not be changed by this module,
so the value of the memory where 'pRTC' points to will not be changed.
But the variable 'pRTC' is allowed to change!
So the code on the page before is correct and works.

Right.
 
Q

quasimodo

If one variable defined const, you can't change variable's value via
this variable.
However it is exactly correct.

#include <stdio.h>

int main()
{
const int num = 12;
int * pNum;

// num = 12; wrong. you can't change a const variable's value.

pNum = &num;
*pNum = 13; // this is perfectly correct.
// num isn't 12 anymore

printf("%d", num);

}

#define SIZE 10;

means SIZE is 10 in everywhere.
 
P

Peter Nilsson

Jean-Marc Bourguet said:
An object which has been declared const
s/declared/defined/

may not be modified without undefined behaviour. But you may
get const view of non const objects. In the later case, it is
possible that you have two aliases, one const, one not and then
it is possible to modify the object. And I'm pretty sure but
I've not checked -- that you can even cast the const away of a
const view while staying in the defined realm.

You can, though it's generally ill advised.
void f1(int const* p1, int* p2) {
*p2 = 42;
}

void f2(int const* p1) {
*(int*)p1 = 36;
}

void foo() {
int const i1 = 1;
int i2 = 2;

f1(&i1, (int*)&i1); /* trigger undefined behaviour */
f2(&i1); /* trigger undefined behaviour */
f1(&i2, &i2); /* no undefined behaviour */
f2(&i2); /* probably no undefined behaviour */
}

The last line is okay since i2 is not const qualified; but again:
the action of f2() is ill advised.
 
M

Mark McIntyre

Rohit said:
Hi all,

I have a doubt in const keyword. My understanding says that a variable
declared const can not be modified by the module it is defined in. Then
consider the following code segment:
To my surprise it increments value of p by one where p has to be a
constant. Please clarify my doubt.

"if you lie to the compiler, it will get its revenge".

const means the compiler will not let you overtly change the value. You
can still lie, cast away the constness, use a pointer to access it, and
so forth. The result is a broken programme. It may still compile, if
you've been devious enough. How many warnings did you get?
 
P

Peter Nilsson

[Please quote the material relevant to your reply. Please also
read previous responses in the thread to avoid repeating
mistakes that have already been corrected.]
If one variable defined const, you can't change variable's
value via this variable.
However it is exactly correct.

By "it" do you mean what follows? If so, you're mistaken.
#include <stdio.h>

int main()
{
const int num = 12;
int * pNum;

// num = 12; wrong. you can't change a const variable's value.

pNum = &num;

This is the same error the OP had. It violates a constraint and
requires a diagnostic.
*pNum = 13; // this is perfectly correct.
// num isn't 12 anymore

Even applying a cast in the assignment of pNum above, the
subsequent behaviour of this line is not defined by the C
standard. So it's pointless saying what num will or won't
be.
printf("%d", num);

The last line of a text stream should be terminated with
a newline for maximally portable code.
}

#define SIZE 10;
means SIZE is 10 in everywhere.

No it means SIZE will expand to 10; (i.e. 10 followed by a semi-
colon).

I advise you to read the FAQ and fix some of your own misconceptions
before trying to educate others.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top