By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,421 Members | 1,127 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,421 IT Pros & Developers. It's quick & easy.

question on const

P: n/a
Hello,

Here is the program

#include stdio

int main(void)
{
const int num = 100;
int *ip;

ip = (int *)#
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
}
Output:
value of num is 100(200)

The output says that *ip is changed and 'num' is unchanged. How is this
possible when both of them point to the same memory location? My wild guess
says that this trick is handled at the compiler level. Am I correct?

Even when the memory location is accessable and the contents changed the
'const integer' is unaffected.

Thanks
Nov 14 '05 #1
Share this Question
Share on Google+
83 Replies


P: n/a

"user" <no**@none.com> wrote in message news:3f******@usenet01.boi.hp.com...
Hello,

Here is the program

#include stdio

#include <stdio.h>
int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
return 0;
}
Output:
value of num is 100(200)


On my system the output is

value of num is 200(200)

[..]
Nov 14 '05 #2

P: n/a
Hello,

I am sorry. After reading the post myself, I felt that the post is
incomplete in itself.

Well when I tried this exercise I expected the code to fail in the
compilation phase with an error ( not a warning). It did not, and the output
made me think how is this possible to have 2 different value when I am
pointing to the same memory location? I exptected the output to 2 100s or 2
200s. Is 'num' variable pointing some where ????

My question is how is the output different? Is the program performing an
undefined behavior?

Thanks

"user" <no**@none.com> wrote in message news:3f******@usenet01.boi.hp.com...
Hello,

Here is the program

#include stdio

int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
}
Output:
value of num is 100(200)

The output says that *ip is changed and 'num' is unchanged. How is this
possible when both of them point to the same memory location? My wild guess says that this trick is handled at the compiler level. Am I correct?

Even when the memory location is accessable and the contents changed the
'const integer' is unaffected.

Thanks

Nov 14 '05 #3

P: n/a
I think the int* p find a new adress in order to write something to that
adress.
If you write const int* ip in that case the adress of ip can't change.
If you assign anything to int *ip it will be assigned to an adress which the
computer will find in order to store it there.

--

---------------------------
Time to get it done!

Remove (d*elete*) to reply

"user" <no**@none.com> wrote in message news:3f******@usenet01.boi.hp.com...
Hello,

Here is the program

#include stdio

int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
}
Output:
value of num is 100(200)

The output says that *ip is changed and 'num' is unchanged. How is this
possible when both of them point to the same memory location? My wild guess says that this trick is handled at the compiler level. Am I correct?

Even when the memory location is accessable and the contents changed the
'const integer' is unaffected.

Thanks

Nov 14 '05 #4

P: n/a
"user" <no**@none.com> writes:
#include stdio
Do you mean

#include <stdio.h>

?
int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
You forgot to return something from the `main' function. Insert

return 0;
}
The behavior of this program is undefined according to section 6.7.3#5 of
the standard: "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. [...]"
Output:
value of num is 100(200)

The output says that *ip is changed and 'num' is unchanged. How is this
possible when both of them point to the same memory location?
Since the behavior is undefined, virtually anything can happen.
My wild guess says that this trick is handled at the compiler level. Am
I correct?


I don't know what you mean by "this trick".

Martin
Nov 14 '05 #5

P: n/a

"user" <no**@none.com> wrote in message news:3f******@usenet01.boi.hp.com...
Hello,

I am sorry. After reading the post myself, I felt that the post is
incomplete in itself.

Well when I tried this exercise I expected the code to fail in the
compilation phase with an error ( not a warning). It did not, and the output made me think how is this possible to have 2 different value when I am
pointing to the same memory location? I exptected the output to 2 100s or 2 200s. Is 'num' variable pointing some where ????

My question is how is the output different? Is the program performing an
undefined behavior?

Thanks

"user" <no**@none.com> wrote in message

news:3f******@usenet01.boi.hp.com...
Hello,

Here is the program

#include stdio

int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
}
Output:
value of num is 100(200)

The output says that *ip is changed and 'num' is unchanged. How is this
possible when both of them point to the same memory location? My wild

guess
says that this trick is handled at the compiler level. Am I correct?

Even when the memory location is accessable and the contents changed the
'const integer' is unaffected.

Thanks


Hello,

Sorry for top posting (in my earlier post). I am trying this on a OpenVMS
Alpha system.

Thanks
Nov 14 '05 #6

P: n/a
Please don't top-post. Please don't put a lot of quoted material in your
signature. Your signature is 36 lines long, which is 32 lines more than
the allowed four lines.

"Frane Roje" <frane.roje(d*elete*)@st.hinet.hr> writes:
I think the int* p find a new adress in order to write something to that
adress.
I'm not sure if I understand you correctly, but you seem to believe that
the definition of a pointer automatically allocates memory. That is not the
case.
If you write const int* ip in that case the adress of ip can't change.


Once you have defined a variable, pointer or other type, const-qualified
or not, its /address/ cannot change throughout its lifetime.

The /value/ of `ip' can certainly be changed. The object pointed to by
`ip' cannot (unless another access path to the same object exists).

Martin
Nov 14 '05 #7

P: n/a
On Thu, 08 Jan 2004 15:02:12 +0530, user wrote:
Well when I tried this exercise I expected the code to fail in the
compilation phase with an error ( not a warning). It did not, and the output
made me think how is this possible to have 2 different value when I am
pointing to the same memory location? I exptected the output to 2 100s or 2
200s. Is 'num' variable pointing some where ????


I'll try to explain this way:

#include <stdio.h>

int
main (void)
{
const int num = 100;
int *ip;

ip = (int *) &num;
*ip = 200;
printf ("value of num is %d(%d) \n", num, *ip);
printf ("address of ip is 0x%p\n", ip);
printf ("address of num is 0x%p\n", &num);
}

this will print out the addresses the pointers are pointing to.
The output is as expected: the address is the same.

Now, I'm not sure of what i'm about to say, but well, correct me if
I am wrong :)

I *think* that the problem is in what we had declared constant, or, better,
in what the compiler sees as a constant.

const int num = 100, we have declared the variable num, it's *name*,
to be constant. We cannot change the value *through that symbol*,
but nothing prevents us by changing it by other means.
Let's assume this declaration is the same as

int *const num = 100;

This is a constant pointer.
You cannot change it's address, but you can change the data.
The other way is

const int *num = 100;

Here the data is constant, we cannot change the data but we can change the
address the variable points to.
So, AFAIK, it may be correct to make the assumption that when we declare
a

const int num

we are actually declaring (or the compiler is actually going to change it
to) the former:

int *const num

that is a constant pointer. But sintactically we handle it as a normal
variable, with the constraint that we cannot change it's value
*through the symbol itself*, and being it a normal variable, and not a
pointer, we cannot either directly change it's address. But indirectly
we can.

So accessing it by

num = 100;

is only a sintactical error, because the compiler knows that that
*variable name* is constant.

I mean, I *think* that the compiler doesn't make assumptions on the data
pointed by that name, but only on the name itself.

Bye
Daniele "tinybyte" Milan

Nov 14 '05 #8

P: n/a
Martin Dickopp <ex****************@zero-based.org> writes:
I'm not sure if I understand you correctly, but you seem to believe that
the definition of a pointer automatically allocates memory. That is not the
case.


I noticed that my statement is ambiguous. To clarify, the definition of
a pointer automatically allocates memory for the pointer itself, but it
doesn't allocate any memory at the location the pointer points to.

Martin
Nov 14 '05 #9

P: n/a
[You have top-posted yet again. Please stop.]

Frane Roje wrote:
I think the int* p find a new adress in order to write something to that
adress.
I can't make sense of that at all.
If you write const int* ip in that case the adress of ip can't change.
When /can/ the address of a named object change?
If you assign anything to int *ip it will be assigned to an adress which the
computer will find in order to store it there.


I can't make sense of that either.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #10

P: n/a
On Thu, 08 Jan 2004 14:57:21 +0530, Vijay Kumar R Zanvar wrote:
On my system the output is

value of num is 200(200)


on my system is 200(200) too, using gcc.
I think that being an undefined behavior according to the standard,
as Martin pointed out, the developers of the compiler used by user
have made up a mess. gcc handles it logically, as I have explained
(hope to be correct) in my earlier followup.

Now, user, which compiler have you used? I'm curious about it.

Bye
Daniele "tinybyte" Milan

Nov 14 '05 #11

P: n/a
user wrote:
Hello,
Please don't top-post. It's rude.

I am sorry. After reading the post myself, I felt that the post is
incomplete in itself.

Well when I tried this exercise I expected the code to fail in the
compilation phase with an error ( not a warning). It did not, and the output
made me think how is this possible to have 2 different value when I am
pointing to the same memory location? I exptected the output to 2 100s or 2
200s. Is 'num' variable pointing some where ????

My question is how is the output different? Is the program performing an
undefined behavior?


Yes. This should be fairly obvious.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #12

P: n/a
tinybyte wrote:
On Thu, 08 Jan 2004 15:02:12 +0530, user wrote:

Well when I tried this exercise I expected the code to fail in the
compilation phase with an error ( not a warning). It did not, and the output
made me think how is this possible to have 2 different value when I am
pointing to the same memory location? I exptected the output to 2 100s or 2
200s. Is 'num' variable pointing some where ????

I'll try to explain this way:

#include <stdio.h>

int
main (void)
{
const int num = 100;
int *ip;

ip = (int *) &num;
*ip = 200;
printf ("value of num is %d(%d) \n", num, *ip);
printf ("address of ip is 0x%p\n", ip);
printf ("address of num is 0x%p\n", &num);


These last two statements invoke undefined behavior. %p is for void
pointers only. It's also a little silly to add your own 0x prefix. On
some implementations you'll get output like

0x0x034aff30
}

this will print out the addresses the pointers are pointing to.
The output is as expected: the address is the same.

Now, I'm not sure of what i'm about to say, but well, correct me if
I am wrong :)


There's no good reason to try to explain undefined behavior. In this
case, the compiler probably eliminated a fetch from memory by using the
value 100 directly, since it "knew" that's what the stored value would be.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #13

P: n/a
>When /can/ the address of a named object change?
sorry I wanted to say the adress that the pointer points to
If you assign anything to int *ip it will be assigned to an adress which the computer will find in order to store it there.

I'm not sure about this but I think that when you write int *p=20; the
compiler will handle the memmory allocation of the int which has '20' value.
--

---------------------------
Time to get it done!

Remove (d*elete*) to reply


Nov 14 '05 #14

P: n/a
On Thu, 08 Jan 2004 10:39:30 +0000, Kevin Goodsell wrote:
There's no good reason to try to explain undefined behavior. In this
case, the compiler probably eliminated a fetch from memory by using the
value 100 directly, since it "knew" that's what the stored value would be.


There's always a good reason to try to know how things really works.
Now we had discovered that that compiler is broken. gcc handles the
thing correctly, as it should be. Just saying "according to the
standard" isn't enough. According to the standard that piece of code
is broken, but it actually executes, and sometimes properly.
You're not compiling programs with the standard, but with compilers.

Daniele
Nov 14 '05 #15

P: n/a
On Thu, 08 Jan 2004 10:39:30 +0000, Kevin Goodsell wrote:
These last two statements invoke undefined behavior. %p is for void
pointers only. It's also a little silly to add your own 0x prefix. On


I admit it's silly :)
Undefined behavior? then cast that pointers to void and you're done.

...
printf ("address of ip is %p\n", (void *)ip);
printf ("address of num is %p\n", (void *)&num);
...

Daniele
Nov 14 '05 #16

P: n/a
Frane Roje wrote:
I'm not sure about this but I think that when you write int *p=20; the
compiler will handle the memmory allocation of the int which has '20' value.


No, it will not. Unless You make p point somewhere decent first the
above is wrong.

--
Thomas

Nov 14 '05 #17

P: n/a
tinybyte <ne******@box.it> wrote:
On Thu, 08 Jan 2004 14:57:21 +0530, Vijay Kumar R Zanvar wrote:
On my system the output is

value of num is 200(200)
on my system is 200(200) too, using gcc.
I think that being an undefined behavior according to the standard,
as Martin pointed out, the developers of the compiler used by user
have made up a mess.


No, the compiler used by the OP is quite as logical as gcc, and possibly
better at optimising - it seems to have diked out all references to the
const int and replaced them with the constant value, which is both a
sensible optimisation, and potentially quite a valuable one.
gcc handles it logically,


s/logically/lazily/, IYAM.

Richard
Nov 14 '05 #18

P: n/a
tinybyte <ne******@box.it> wrote:
On Thu, 08 Jan 2004 10:39:30 +0000, Kevin Goodsell wrote:
There's no good reason to try to explain undefined behavior. In this
case, the compiler probably eliminated a fetch from memory by using the
value 100 directly, since it "knew" that's what the stored value would be.
There's always a good reason to try to know how things really works.
Now we had discovered that that compiler is broken. gcc handles the
thing correctly, as it should be.


Wrong, and wrong. The OP's compiler is quite correct, and gcc handles
this code as it _may_, not as it _should_ be handled. The code invokes
undefined behaviour - changing the value of a const object - and _any_
behaviour after that is correct.
Just saying "according to the
standard" isn't enough. According to the standard that piece of code
is broken, but it actually executes, and sometimes properly.
For _some_ values of properly. _My_ value of properly is the reverse -
I'd rather have a compiler that compiles correct code to a fast
executable than one that compiles incorrect code to appear to be
correct. Hence, I'd prefer the OP's compiler to gcc.
You're not compiling programs with the standard, but with compilers.


A meaningless statement, really.

Richard
Nov 14 '05 #19

P: n/a
tinybyte wrote:
On Thu, 08 Jan 2004 10:39:30 +0000, Kevin Goodsell wrote:
There's no good reason to try to explain undefined behavior. In this
case, the compiler probably eliminated a fetch from memory by using the
value 100 directly, since it "knew" that's what the stored value would be.

There's always a good reason to try to know how things really works.
Now we had discovered that that compiler is broken.


No we have not.
gcc handles the
thing correctly, as it should be.
No it does not. There is no right way and there is no wrong way.
Just saying "according to the
standard" isn't enough.
Yes it is.
According to the standard that piece of code
is broken, but it actually executes, and sometimes properly.
There is no properly.
You're not compiling programs with the standard, but with compilers.


Which conform to a standard. When the standard says that something is
undefined you cannot rely on the behaviour of any compiler when using
that something. The result will be different between different compilers
hence rendering your code unportable. The result will be different
between different versions of the same compiler. The result will even be
different for the same compiler invoked with different flags.

Try compiling with the optimising flags for gcc and be prepared to learn
a valuable lesson.

--
Thomas.

Nov 14 '05 #20

P: n/a
Richard Bos wrote:


s/logically/lazily/, IYAM.

^^^^
?
DYM "ITYM"?

:)

--
Thomas.

Nov 14 '05 #21

P: n/a
But if I use a char* p="test";
In that case the computer will allocate some space for the array,
right?

--

---------------------------
Time to get it done!

Remove (d*elete*) to reply
Nov 14 '05 #22

P: n/a
Frane Roje wrote:
But if I use a char* p="test";
In that case the computer will allocate some space for the array,
right?


Yes, but this is different. The compiler will find memory for the string
literal, then you make the pointer point to it. (Note that the string
cannot be changed).

Memory is also allocated for the string when you do:

puts("test");

It is in fact also not impossible for the string in the call to puts and
the string pointed to by p to be the same string. Remember that the
value you get from evaluating "test" is a pointer. Also in the above you
are assigning to the pointer, not to wherever the pointer is pointing.

In the case of

int *ip;
*ip = 42;

You are dereferencing ip and you get whatever it is pointing to. Bad
thing. Note that 42 evaluated to an int not an address.

--
Thomas.

Nov 14 '05 #23

P: n/a
Thomas Stegen <ts*****@cis.strath.ac.uk> wrote:
Richard Bos wrote:
s/logically/lazily/, IYAM.

^^^^
DYM "ITYM"?


If You Ask Me.

Richard
Nov 14 '05 #24

P: n/a
"Frane Roje" <frane.roje(d*elete*)@st.hinet.hr> wrote:
But if I use a char* p="test";
In that case the computer will allocate some space for the array,
right?


Wrong. It will put a (unwritable!) string constant somewhere in memory,
and then make p point to it. The string constant being unwritable is
significant - you've been writing through that pointer in this thread,
and you cannot reliably do so if p points to a string constant.

Richard
Nov 14 '05 #25

P: n/a
In article <bt*************@news.t-online.com> Martin Dickopp <ex****************@zero-based.org> writes:
const int num = 100;
int *ip;
ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip); .... Output:
value of num is 100(200)

The output says that *ip is changed and 'num' is unchanged. How is this
possible when both of them point to the same memory location?


Since the behavior is undefined, virtually anything can happen.


I think the compiler performs optimisation. That is, because num is
defined to be constant the compiler is allowed to assume that in the
printf num is still 100, so it does not access the value stored at
num at all.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #26

P: n/a
On Thu, 08 Jan 2004 12:17:51 +0000, Thomas Stegen wrote:
Now we had discovered that that compiler is broken.
No we have not.


You're right.
gcc handles the
thing correctly, as it should be.


No it does not. There is no right way and there is no wrong way.


You're right.
Just saying "according to the
standard" isn't enough.


Yes it is.


No, it's not. We should go deeper than the standard. I want to learn
more than what's written in the standard, and you're helping me.
If we stop discussing when someone says "According to the standard there
is no reason to speak about this" no one will learn further, even if
possible. Now, please tell me, if this is comp.lang.c "We speak about
everything that is C related" or if "We speak only
about what is written in the C standard". Both are ok for me, but for the
latter I'll know I had to search
somewhere else for the huge deal of information we would be missing.
According to the standard that piece of code
is broken, but it actually executes, and sometimes properly.


There is no properly.


You're right.
You're not compiling programs with the standard, but with compilers.


Which conform to a standard. When the standard says that something is
undefined you cannot rely on the behaviour of any compiler when using
that something. The result will be different between different compilers
hence rendering your code unportable. The result will be different
between different versions of the same compiler. The result will even be
different for the same compiler invoked with different flags.


You're right, but I would have never learned the lesson if I sticked to
the "According to the standard" dogma. We cannot rely on the behaviour of
any compiler, but we can surely speak about every and each different
behaviour, and maybe learn something more. C language is standard +
compilers, not only standard, that's what I meant.
Try compiling with the optimising flags for gcc and be prepared to learn
a valuable lesson.


I've learned NOW. Many thanks to all of you. I want to learn, but I cannot
if we stop when the standard comes in.

Daniele
Nov 14 '05 #27

P: n/a
In article <pa****************************@box.it> tinybyte <ne******@box.it> writes:
On Thu, 08 Jan 2004 10:39:30 +0000, Kevin Goodsell wrote:
There's no good reason to try to explain undefined behavior. In this
case, the compiler probably eliminated a fetch from memory by using the
value 100 directly, since it "knew" that's what the stored value would be.
There's always a good reason to try to know how things really works.
Now we had discovered that that compiler is broken. gcc handles the
thing correctly, as it should be.


In what way is that compiler broken and gcc not? A compiler is allowed,
when it sees a declaration like
const int num = 100;
to assume that when you use "num" later in the program, your intention
is that the value 100 should be used.
According to the standard that piece of code
is broken, but it actually executes, and sometimes properly.


What is proper execution with a piece of code to which the standard
assigns no meaning?
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #28

P: n/a
In article <3f***************@news.individual.net> rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
No, the compiler used by the OP is quite as logical as gcc, and possibly
better at optimising - it seems to have diked out all references to the
const int and replaced them with the constant value, which is both a
sensible optimisation, and potentially quite a valuable one.


What gcc probably does do (and the warning message you get suggests it)
is discarding the word const from the declaration of num. Normally gcc
performs the above optimisation.
gcc handles it logically,


s/logically/lazily/, IYAM.


Not lazy...
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #29

P: n/a
On Thu, 08 Jan 2004 12:21:13 +0000, Dik T. Winter wrote:
In what way is that compiler broken and gcc not? A compiler is allowed,
when it sees a declaration like
const int num = 100;
to assume that when you use "num" later in the program, your intention
is that the value 100 should be used.
But it returns the same address. That's inconsistent. It should be not
permitted if not according to the standard, but it is. This means:
compilers implementations are broken, not strictly following the standard.
What is proper execution with a piece of code to which the standard
assigns no meaning?


There is no proper execution, now I know.

Bye
Daniele
Nov 14 '05 #30

P: n/a
It seems to be compiler dependent and even changes with optimisations.

<jm@paris>13:42:33~$gcc -v
Reading specs from /usr/lib/gcc/i686-pc-linux-gnu/3.4.0/specs
Configured with: ../gcc/configure --prefix=/usr --enable-shared
--enable-static --enable-debug --enable-profile --verbose --enable-interpreter
--enable-haifa --enable-long-long --enable-languages=c,c++ --with-system-zlib
--enable-__cxa_atexit --enable-threads=posix
Thread model: posix
gcc version 3.4.0

<jm@paris>13:43:51~$gcc ess.c
<jm@paris>13:44:26~$./a.out
value of num is 200(200)

<jm@paris>13:44:28~$gcc -Wall -W -O2 ess.c
ess.c: In function `main':
ess.c:11: warning: control reaches end of non-void function
<jm@paris>13:44:41~$./a.out
value of num is 100(200)

Regards,

Jm

user wrote:
Hello,

Here is the program

#include stdio

int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
}
Output:
value of num is 100(200)

The output says that *ip is changed and 'num' is unchanged. How is this
possible when both of them point to the same memory location? My wild guess
says that this trick is handled at the compiler level. Am I correct?

Even when the memory location is accessable and the contents changed the
'const integer' is unaffected.

Thanks


Nov 14 '05 #31

P: n/a
Thomas Stegen wrote:

Frane Roje wrote:
I'm not sure about this but I think that when you
write int *p=20;
the compiler will handle the memmory allocation
of the int which has '20' value.


No, it will not. Unless You make p point somewhere decent first the
above is wrong.


int *p=20;
is an initialization, so you can't make p point somewhere decent first.

Also, a cast is required to assign an integer value to a pointer,
and the result might not be defined.

--
pete
Nov 14 '05 #32

P: n/a
tinybyte wrote:

On Thu, 08 Jan 2004 12:21:13 +0000, Dik T. Winter wrote:
In what way is that compiler broken and gcc not? A compiler is allowed,
when it sees a declaration like
const int num = 100;
to assume that when you use "num" later in the program, your intention
is that the value 100 should be used.


But it returns the same address. That's inconsistent. It should be not
permitted if not according to the standard, but it is. This means:
compilers implementations are broken,
not strictly following the standard.
What is proper execution with a piece of code to which the standard
assigns no meaning?


There is no proper execution, now I know.


I hope you understand that the compiler can't be wrong
when there is no proper execution.

--
pete
Nov 14 '05 #33

P: n/a
On Thu, 08 Jan 2004 13:20:48 +0000, pete wrote:
I hope you understand that the compiler can't be wrong
when there is no proper execution.


Compilers simply must not permit such a thing, if it gives an
undefined behavior.

Daniele
Nov 14 '05 #34

P: n/a
"tinybyte" <ne******@box.it> wrote in message
news:pa****************************@box.it...
On Thu, 08 Jan 2004 13:20:48 +0000, pete wrote:
I hope you understand that the compiler can't be wrong
when there is no proper execution.


Compilers simply must not permit such a thing, if it gives an
undefined behavior.


Are you trying to say that all possible undefined behaviour must be detected
at compile time, resulting in an error? If not, what are you trying to say?
Nov 14 '05 #35

P: n/a
In article <pa****************************@box.it> tinybyte <ne******@box.it> writes:
On Thu, 08 Jan 2004 12:21:13 +0000, Dik T. Winter wrote:
In what way is that compiler broken and gcc not? A compiler is allowed,
when it sees a declaration like
const int num = 100;
to assume that when you use "num" later in the program, your intention
is that the value 100 should be used.


But it returns the same address. That's inconsistent.


No that is not inconsistent. The address *must* remain the same.
The question is: "must the compiler look at that address to see what
is there?" The answer to that question is *no* if the variable is
declared to be const, because the compiler is allowed to assume that
the value is not changed.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #36

P: n/a
tinybyte wrote:

On Thu, 08 Jan 2004 13:20:48 +0000, pete wrote:
I hope you understand that the compiler can't be wrong
when there is no proper execution.


Compilers simply must not permit such a thing, if it gives an
undefined behavior.


Is that how you think C is,
or is that your opinion on how you think C should be ?

--
pete
Nov 14 '05 #37

P: n/a
On Thu, 08 Jan 2004 14:20:15 +0000, Alex wrote:
Are you trying to say that all possible undefined behaviour must be detected
at compile time, resulting in an error? If not, what are you trying to say?


Yes, they should be detected, and result in an error.

Daniele
Nov 14 '05 #38

P: n/a
On Thu, 08 Jan 2004 14:54:22 +0000, pete wrote:
tinybyte wrote:
or is that your opinion on how you think C should be ?


Is an opinion on how C compilers should be.

Daniele
Nov 14 '05 #39

P: n/a
On Thu, 08 Jan 2004 14:31:51 +0000, Dik T. Winter wrote:
No that is not inconsistent. The address *must* remain the same.
The question is: "must the compiler look at that address to see what
is there?" The answer to that question is *no* if the variable is
declared to be const, because the compiler is allowed to assume that
the value is not changed.


The compiler is allowed to assume that the value it's not changed, but
sometimes it is changed, sometimes not, depends on optimization.
This is inconsistent behavior for me, and in C programming this should
not be ALLOWED. That is all I'm talking about.
I'm trying to say that compilers aren't perfect. And that all those
standards everyone here care so much about are not of any help in this case.
A value that cannot be changed has been changed, under certain conditions.
That means something is broken.

Is the same as you have an application that normally gives perfect output,
but by using it in a different way it was written for, you can screw up
the whole thing. You should not be allowed to use it that way.
If you can, there is a bug.

Bye
Daniele
Nov 14 '05 #40

P: n/a
begin tinybyte:
The compiler is allowed to assume that the value it's not changed,
but sometimes it is changed, sometimes not, depends on optimization.
It is not changed by magic but by your request.
Using an explicit cast. You asked for trouble, you got trouble.
If you fix this line

ip = (int *) &num;

to

ip = &num;

you should get a diagnostic similar to

warning: assignment discards qualifiers from pointer target type

If you change the declaration to

const int *ip;

then the diagnostic will change to

warning: assignment of read-only location
This is inconsistent behavior for me, and in C programming this
should not be ALLOWED.
C gives you enough rope to hang yourself.
And then a couple of more feet, just to be sure.
Always has been, always will be.
[...] A value that cannot be changed has been changed, under
certain conditions. That means something is broken.


There are indeed languages out there that protect the code from
hostile programmers, e.g. Smalltalk, Java, C#, Python, Ruby.
If you want that, go for it.

--
Für Google, Tux und GPL!
Nov 14 '05 #41

P: n/a
tinybyte wrote:
On Thu, 08 Jan 2004 14:20:15 +0000, Alex wrote:
Are you trying to say that all possible undefined behaviour
must be detected at compile time, resulting in an error? If
not, what are you trying to say?


Yes, they should be detected, and result in an error.


#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int main(void)
{
int a, b, c;

a = INT_MAX;
b = rand();
(void)printf("%d\n", c = a + b);
return 0;
}

has a fairly high probability of generating undefined behavior.
Yet very few systems will complain at run-time whether or not UB
occurs, and none that I know of will complain at compile time.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #42

P: n/a
*** Please do NOT top-post - corrected ***
Jean-Michel Collard wrote:
user wrote:
Here is the program

#include stdio

int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
}
Output:
value of num is 100(200)
.... snip ...
It seems to be compiler dependent and even changes with optimisations.

<jm@paris>13:42:33~$gcc -v
Reading specs from /usr/lib/gcc/i686-pc-linux-gnu/3.4.0/specs
Configured with: ../gcc/configure --prefix=/usr --enable-shared
--enable-static --enable-debug --enable-profile --verbose --enable-interpreter
--enable-haifa --enable-long-long --enable-languages=c,c++ --with-system-zlib
--enable-__cxa_atexit --enable-threads=posix
Thread model: posix
gcc version 3.4.0

<jm@paris>13:43:51~$gcc ess.c
<jm@paris>13:44:26~$./a.out
value of num is 200(200)

<jm@paris>13:44:28~$gcc -Wall -W -O2 ess.c
ess.c: In function `main':
ess.c:11: warning: control reaches end of non-void function
<jm@paris>13:44:41~$./a.out
value of num is 100(200)


With the silly top-posting fixed this may make some sense.

Something is seriously wrong with your gcc installation:

c:\c\junk>gcc -W -Wall -ansi -pedantic -O1 junk.c
junk.c:1:10: #include expects "FILENAME" or <FILENAME>
junk.c: In function `main':
junk.c:9: warning: implicit declaration of function `printf'
junk.c:10: warning: control reaches end of non-void function

After correcting the source and removing the foolish cast:

#include <stdio.h> /* corrected */
int main(void)
{
const int num = 100;
int *ip;

ip = &num; /* silly cast removed */
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);
return 0; /* line added */
}

c:\c\junk>gcc -W -Wall -ansi -pedantic -O1 junk.c
junk.c: In function `main':
junk.c:7: warning: assignment discards qualifiers from pointer
target type

Moral: CASTS ARE EVIL.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #43

P: n/a
tinybyte wrote:

On Thu, 08 Jan 2004 14:20:15 +0000, Alex wrote:
Are you trying to say that all possible undefined behaviour must be detected
at compile time, resulting in an error? If not, what are you trying to say?


Yes, they should be detected, and result in an error.

Then it wouldn't be undefined behavior.

Brian Rodenborn
Nov 14 '05 #44

P: n/a
On Thu, 08 Jan 2004 17:36:30 +0100, Alexander Bartolich wrote:
begin tinybyte:
It is not changed by magic but by your request.
Using an explicit cast. You asked for trouble, you got trouble.
I asked for that, I've got it, I can manage it, now I'm happy :)
C gives you enough rope to hang yourself.
And then a couple of more feet, just to be sure.
Always has been, always will be.
Nowadays too many programmers hangs themselves using C.
Knowing every inch of that rope is the only way to stay away from
hanging...
There are indeed languages out there that protect the code from
hostile programmers, e.g. Smalltalk, Java, C#, Python, Ruby.
If you want that, go for it.


I don't want that. I will keep programming in C for my whole life, because
I love it. Knowing many languages is indeed useful, even if you actually
program only in C. I don't want another language, I want the C language
the best it can be. This is the whole point of my polemic

....

Am I too much polemic? ;)

Bye
Daniele
Nov 14 '05 #45

P: n/a
The original post is missing on my server, so I am replying to
a followup.
int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
The effect at this point is officially undefined by the C standard,
so *anything* *could* happen. What likely *does* happen is just
what is shown below:
printf("value of num is %d(%d) \n", num, *ip);
}

In article <3F***************@france-paris.org>
Jean-Michel Collard <jm@france-paris.org> writes:It seems to be compiler dependent and even changes with optimisations. [without optimization]value of num is 200(200) [with optimization]value of num is 100(200)


This is highly expect-able. :-)

First, remember that the "const" keyword in C is peculiarly named,
like so many C keywords: "struct" means "define a type"; "typedef"
means "do NOT define a new type"; "static" has nothing to do with
electricity :-) ; and "const" means "read-only".

Thus:

const int num = 100;

means: "Allocate a plain old ordinary variable that could change
like any plain old ordinary variable, but please Mr Compiler, if
you are able and willing, please put it into memory that is in fact
read-only. Oh and by the way I also promise never, ever to change
this variable -- you may count on me sir, I never make misteaks!" (sic)

Now, as it happens, gcc is not able or willing to place this variable
in read-only memory (because gcc assumes there is a conventional
stack, and puts all its automatic variables on that stack, and does
not try to protect any sub-parts of it against writing). If you
compile without optimization, gcc also forgets about your promise
not to change the variable.

On the other hand, if you turn on optimization, gcc remembers your
promise. You promised the variable "num" would always be 100 --
so the printf() call can substitute in the promised value for the
first %d.

The pointer "ip", of course, points to the actual variable (which
the compiler did not place in read-only memory after all) that
was initially 100. You achieved this by using a cast to tell the
compiler: "Hey Mr Compiler, I am smarter than you: this pointer
value from &num, that has type `pointer to read-only int', really
points to a read/write int. So even though this assignment is
suspicious and dodgy and you would normally tell me I am doing
something foolish, I invoke the All-Powerful-Cast syntax to shut
you up!" And -- because gcc was unwilling or unable to put "num"
in really, truly read-only memory, this, too, is actually correct.
The variable "num" *is* an ordinary int variable when gcc is done
compiling, because -- despite your asking gcc to please put it in
read-only memory -- it went into read/write memory.

Then, when you said "*ip = 200;" you told the compiler to change
the value of the memory from its original 100 to the new 200.
The compiler no doubt generated code to do this, and since "num"
was -- despite your request -- in read/write memory, the assignment
changed it.

Thus, you broke your promise never to change "num".

You lied to the compiler. It got its revenge, by producing different
code under optimization (where it assumed you kept your promise)
than without optimization (where it did not).

Note that it requires a pointer cast to achieve this lie. Avoid
pointer casts and you will avoid many mistakes. This is part of
the reason comp.lang.c wisdom says "do not cast malloc()".
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #46

P: n/a
On Thu, 08 Jan 2004 18:55:08 +0000, Chris Torek wrote:
The original post is missing on my server, so I am replying to
a followup. [snip] Note that it requires a pointer cast to achieve this lie. Avoid
pointer casts and you will avoid many mistakes. This is part of
the reason comp.lang.c wisdom says "do not cast malloc()".


Ah, finally an exaustive explanation that isn't "according to the standard
there is no reason to speak about it" ... thanks a real lot Chris!
If we ever met in the future, remember that I owe you a beer! :D

Bye,
Daniele "tinybyte" Milan
Nov 14 '05 #47

P: n/a
[Cross-posted and followups set to gnu.gcc.help.]

[Note: Discussion arose from a question about strange output when a
const object is modified through a pointer with the const attribute cast
away. The OP observed that the same address appeared to contain 2
different values, depending on whether it was accessed by the const
object name or by dereferencing the pointer - typical newbie stuff
dealing with undefined behavior. Others observed that gcc doesn't seem
to do the optimization that causes the apparently strange result. OP's
code (slightly adapted) appears in my example session below.]

Dik T. Winter wrote:
In article <3f***************@news.individual.net> rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
> No, the compiler used by the OP is quite as logical as gcc, and possibly
> better at optimising - it seems to have diked out all references to the
> const int and replaced them with the constant value, which is both a
> sensible optimisation, and potentially quite a valuable one.


What gcc probably does do (and the warning message you get suggests it)
is discarding the word const from the declaration of num. Normally gcc
performs the above optimisation.


gcc doesn't even seem to warn about it with -W -Wall. It looks like
-Wcast-qual (which is one of several additional warning options I
usually enable) enables the warning. But I don't think this warning has
anything to do with the results.

gcc *should* do that optimization, if you turn optimizations on. And it
does... but I found something strange:

$ cat fun.c
#include <stdio.h>

int main(void)
{
const int num = 100;
int *ip;

ip = (int *)&num;
*ip = 200;
printf("value of num is %d(%d) \n", num, *ip);

return 0;
}
$ gcc fun.c -o fun.exe
$ ./fun
value of num is 200(200)
$ gcc -O fun.c -o fun.exe
$ ./fun
value of num is 100(200)
$ gcc -pedantic -O fun.c -o fun.exe
$ ./fun
value of num is 200(200)
Note that I compiled 3 different ways: first, with no special options,
second with basic optimizations turned on, and finally with basic
optimizations and -pedantic turned on. With optimizations (and no
-pedantic) it did the expected optimization. For some reason, turning on
-pedantic changed the results. I checked the docs and this doesn't look
right. -pedantic should only affect what diagnostics are issued, I think.

If -pedantic reduces optimization effectiveness, I think a lot of us are
going to have to change the way we use gcc.

For reference, here's my version info:

$ gcc -v
Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.3.1/specs
Configured with: /GCC/gcc-3.3.1-3/configure --with-gcc --with-gnu-ld
--with-gnu-as --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc
--libdir=/usr/lib --libexecdir=/usr/sbin --mandir=/usr/share/man
--infodir=/usr/share/info
--enable-languages=c,ada,c++,f77,pascal,java,objc --enable-libgcj
--enable-threads=posix --with-system-zlib --enable-nls
--without-included-gettext --enable-interpreter --enable-sjlj-exceptions
--disable-version-specific-runtime-libs --enable-shared
--disable-win32-registry --enable-java-gc=boehm
--disable-hash-synchronization --verbose --target=i686-pc-cygwin
--host=i686-pc-cygwin --build=i686-pc-cygwin
Thread model: posix
gcc version 3.3.1 (cygming special)

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #48

P: n/a
tinybyte <ne******@box.it> spoke thus:
If we ever met in the future, remember that I owe you a beer! :D


There are a number of people here I owe beers to ;D

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #49

P: n/a
tinybyte wrote:
On Thu, 08 Jan 2004 10:39:30 +0000, Kevin Goodsell wrote:

These last two statements invoke undefined behavior. %p is for void
pointers only. It's also a little silly to add your own 0x prefix. On

I admit it's silly :)
Undefined behavior? then cast that pointers to void and you're done.

...
printf ("address of ip is %p\n", (void *)ip);
printf ("address of num is %p\n", (void *)&num);
...


That is the correct way to handle it, but you might want to cast to
const void * in the latter case, otherwise you may elicit a warning from
the compiler, since num is a const object.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #50

83 Replies

This discussion thread is closed

Replies have been disabled for this discussion.