473,387 Members | 1,785 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

complier problem

Hi

My question is : Would the expression *p++=c be disallowed by the
complier.
The answer given in the book is: No.Because here even though the vlue
of p is acced twice it is used to modify two different objects p and
*p.
so can anyone explain this answer to me detail

Jul 28 '06 #1
11 2603


neha wrote On 07/28/06 10:52,:
Hi

My question is : Would the expression *p++=c be disallowed by the
complier.
The answer given in the book is: No.Because here even though the vlue
of p is acced twice it is used to modify two different objects p and
*p.
so can anyone explain this answer to me detail
Before:

c = 42

p --[ 3 ]
[ 1 ]
[ 4 ]

After:

c = 42

[ 42 ]
p --[ 1 ]
[ 3 ]

Two things have changed: The value of c has been copied
to the object p formerly pointed to, and p has been
incremented to point to the next object. The first was
caused by *(something) = c, the second by the p++.

--
Er*********@sun.com

Jul 28 '06 #2
neha wrote:
...
My question is : Would the expression *p++=c be disallowed by the
complier.
...
The answer given in the book is: No.Because here even though the vlue
of p is acced twice it is used to modify two different objects p and
*p.
...
The question does not provide enough information for an answer. And the given
answer does not make sense at all. What book is it? If it says what you say it
says, then you better get another book.

Note, that the question is specifically about whether the expression is allowed
or disallowed by the compiler or, in other words, whether the expression is
well-formed or ill-formed. In order to answer the question we need to know the
types of 'p' and 'c'. For example, if 'p' is of type 'void*', then it is illegal
to apply the '++' operator to it and the compiler will disallow it. If 'p' is of
type 'double*' and 'c' is of type 'struct Foo', then we have completely
unrelated types in assignment, which will also cause a diagnostic from the
compiler. And so on. Without having this extra information, there's no way to
say whether there's something there that must cause the compiler to complain.

The proposed answer, on the other hand, seems to address the well-known issue of
violating the object-access-and-sequence-points rule (don't know a better name
for it). Even if this rule is violated in some code, it does not make the code
ill-formed, i.e. no diagnostic is required from the compiler. It won't be
"disallowed" by the compiler even if there's a problem there. Instead, the code
will produce undefined behavior. There many are other ways, BTW, how the above
expression might produce undefined behavior. But this is irrelevant, since it
has nothing to do with being "disallowed by the compiler".

--
Best regards,
Andrey Tarasevich
Jul 28 '06 #3
neha posted:
My question is : Would the expression *p++=c be disallowed by the
complier.

I presume that that's a typo for:

*p++ = p;
Which means:

Take the object pointed at by "p", and store the value "p" in it. Then
increment "p". Quite like:

*p = p;

++p;

Which, in full context, would have to be something like:

int main()
{
void *ptr[2] = 0;

void **p = ptr;

*p++ = p;
}

--

Frederick Gotham
Jul 28 '06 #4
Eric Sosman wrote:
neha wrote On 07/28/06 10:52,:
Hi

My question is : Would the expression *p++=c be disallowed by the
complier.
The answer given in the book is: No.Because here even though the vlue
of p is acced twice it is used to modify two different objects p and
*p.
so can anyone explain this answer to me detail

Before:

c = 42

p --[ 3 ]
[ 1 ]
[ 4 ]

After:

c = 42

[ 42 ]
p --[ 1 ]
[ 3 ]

Two things have changed: The value of c has been copied
to the object p formerly pointed to, and p has been
incremented to point to the next object. The first was
caused by *(something) = c, the second by the p++.
Actually three things have changed but I take it that one
of those changes is a typo.
Frederick Gotham wrote:
neha posted:
My question is : Would the expression *p++=c be disallowed by the
complier.


I presume that that's a typo for:

*p++ = p;
No , I think that the opening poster wrote what he intended.
He says "the value of p is accessed twice" which seems to
exclude *p++ = p

Spiros Bousbouras

Jul 28 '06 #5


Frederick Gotham wrote On 07/28/06 12:56,:
neha posted:

>>My question is : Would the expression *p++=c be disallowed by the
complier.

I presume that that's a typo for:

*p++ = p;
Which means:

Take the object pointed at by "p", and store the value "p" in it. Then
increment "p". Quite like:

*p = p;

++p;
`*p+ = p' exhibits undefined behavior that the two-line
rewrite does not. 6.5, paragraph 2:

"[...] Furthermore, the prior value shall be read
only to determine the value to be stored."

In `*p++ = p' there are two reads of p's value: the permitted
read on the l.h.s. as part of the ++, and another on the r.h.s.
(Some may think there's a third read to determine the value
that * dereferences, but not so: that value is not the value
of p, but the value of the subexpression p++.)

To put it another way: Why in the two-line rewrite did you
choose to put the assignment first and the increment second?
You could just as well have written

++p;
*p = p;

or (abusing C's syntax to emphasize the U.B.)

++...
*p = p;
...p;

--
Er*********@sun.com

Jul 28 '06 #6
In article <11**********************@i42g2000cwa.googlegroups .com>
neha <ne*********@gmail.comwrote:
>My question is : Would the expression *p++ = c be disallowed by the
complier.
(As an aside, remarkably few things are "disallowed" in C even if they
make no sense. :-) See <http://web.torek.net/torek/c/compiler.html>
for additional remarks.)
>The answer given in the book is: No.Because here even though the vlue
of p is acced twice it is used to modify two different objects p and
*p.
This answer is ... not so great.

Let us assume that the expression:

*p++ = c

is made into a complete statement, so that there are "sequence
points" before and after it. We might as well also assume that p
and c have appropriate types and useful values, otherwise the entire
thing falls apart.

Given these assumptions, we can next note that:

*p++ = c;

is parsed the same as:

(*(p++)) = (c);

This has four sub-expressions, each of which may be evaluated in
any order (perhaps even in parallel), with the obvious requirement
that the value of the "something"s below be known by the time they
are used:

p++

c

*(something) [specifically *p]

(something) = (something) [specifically *p = c]

Each of these four sub-expressions produces a value (of some type);
each can, but need not, also have some "side effect". A "side
effect" is, essentially, a change to something in memory: putting
a new value in some object. (In computer science, "side effects"
can also refer to printing output and the like, but we can ignore
all that here.)

Two of the four expressions above do in fact have side effects,
namely, "p++" and "(something) = (something)".

In C, side effects that cause modifications to objects are allowed
to take place anywhere between "sequence points". If you wish to
avoid undefined behavior, you -- the programmer -- must make sure
that when you make such modifications, you do not "re-access" the
value of the object later, unless the "next" sequence point has
already happened, so that the new value has had time to settle in
to its object.

Think of the new values as raw eggs being tossed in in the air by
a juggler. He is allowed to get as many eggs (values) in the air
as he likes, as long as he catches them all by the next sequence
point, and packs them carefully into their egg-holders (objects)
by then.

What happens if you throw *two* raw-egg-values into the air, aiming
both of them at the same egg-holder? One likely answer is: they
collide and break, making a big mess. So "don't do that".

Now, in this case, we have two new values that have to happen:
"value of p + 1" goes into "p", and "value of c" goes into "*p".
This is where the most subtle point comes in.

The expression "*p = c" modifies *p. Of course, this needs the
value of "p". So "*p++" modifies *p++ ... which needs the value
of ... what?

The obvious (and correct) answer is "the value of p++", but what
exactly *is* the "value of p++"? The answer is *not* "go back and
look at p again", and this is a crucial point! The value of
"p++" is the value p had before the new p+1 value goes into p,
but this value has been "captured", in a sense, by tossing it
up into the air, as one of those raw eggs.

In other words, when you have:

*p++ = c;

the compiler can toss "the value of c" into the air; it does toss
"the old value of p, before incrementing" into the air; and it can
now toss "the new value of p, after incrementing" into the air.
At this point, it has everything it needs to handle the ordinary
assignment expression: it grabs "the old value of p" out of the
air and feeds that to the unary "*" operator. This finds whatever
object is at "*(old value of p)". Since the point of finding that
object is to change it -- to set it to "the value of c" -- the
compiler now aims "the value of c" (either getting it and tossing
it in the air now, if needed, or using the one that is already
there) at this object. The "value of c" egg is now aimed at the
"object at *old_p" egg-cup.

(At this point, there are only two values in the air: "value of c"
aimed towards *old_p and "new value for p" aimed at p. What happened
to "four expressions"? Well, one of them -- *(something) -- was
used to locate an object, so it is not "in the air" anymore. The
last one is the value of the entire assignment, i.e., the value
once *(something) is set. This value is aimed at the trash-can,
so if the compiler is any good, it does not even bother throwing
it up into the air in the first place.)

Now we come to the sequence point. Here, all the action has to
stop for a moment: the new value for p has to get stored safely
into p, and the new value for *(old value of p) has to get stored
safely there. All the "eggs" land in their targets -- with the
value of the overall assignment going into the trash -- and the
sequence point is satisfied; now the compiler can move on to the
next statement.
--
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.
Jul 28 '06 #7
Chris Torek wrote:
>
The obvious (and correct) answer is "the value of p++", but what
exactly *is* the "value of p++"? The answer is *not* "go back and
look at p again", and this is a crucial point! The value of
"p++" is the value p had before the new p+1 value goes into p,
but this value has been "captured", in a sense, by tossing it
up into the air, as one of those raw eggs.
...
Well, while it is true that what we need is the old value of 'p', what you are
saying seems to imply that the only way to obtain that old value of 'p' is to
preserve it ("capture it", "toss it into the air") when it is still available
(before 'p' is incremented). In reality, it is not required to be that way. The
compiler is free to perform the increment first without making any attempts to
"capture" the old value of 'p' and later, when it actually needs the old value
of 'p', it can obtain it by subtracting 1 from the current (already incremented)
value of 'p'.

--
Best regards,
Andrey Tarasevich

Jul 28 '06 #8
[in a situation in which the value of "p++" is used...]

In article <12*************@news.supernews.com>,
Andrey Tarasevich <an**************@hotmail.comwrote:
>Well, while it is true that what we need is the old value of 'p',
what you are saying seems to imply that the only way to obtain that
old value of 'p' is to preserve it ("capture it", "toss it into
the air") when it is still available (before 'p' is incremented).
In reality, it is not required to be that way. The compiler is free
to perform the increment first without making any attempts to
"capture" the old value of 'p' and later, when it actually needs
the old value of 'p', it can obtain it by subtracting 1 from the
current (already incremented) value of 'p'.
This is a valid implementation-specific technique (via the
"as-if" rule), provided p itself is not marked volatile.

That is, regardless whether the compiler turns:

save = p++;

into:

/* effective C code; and machine instructions */
save = p; /* add r1, 0, r2 */
p = p + 1; /* add r1, 1, r1 */

or:

p = p + 1; /* add r1, 1, r1 */
save = p - 1; /* add r1, -1, r2 */

the outcome is the same, as long as p is not "volatile". (And the
code runs just as fast either way, since both sequences use two
"add" instructions with embedded immediate constants; the only
difference is the value of those constants.)

If p *is* marked "volatile", however, the compiler cannot use the
second sequence, since that causes two reads from the object. (As
yet another wrinkle, "what constitutes an access" to one of these
things marked volatile "is implementation-defined", so if the
implementation can provide a particularly interesting interpretation,
it may actually be able to do the "add one, then re-read, then
subtract one" after all.)
--
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.
Jul 28 '06 #9
Ark
Chris Torek wrote:
[in a situation in which the value of "p++" is used...]

In article <12*************@news.supernews.com>,
Andrey Tarasevich <an**************@hotmail.comwrote:
>Well, while it is true that what we need is the old value of 'p',
what you are saying seems to imply that the only way to obtain that
old value of 'p' is to preserve it ("capture it", "toss it into
the air") when it is still available (before 'p' is incremented).
In reality, it is not required to be that way. The compiler is free
to perform the increment first without making any attempts to
"capture" the old value of 'p' and later, when it actually needs
the old value of 'p', it can obtain it by subtracting 1 from the
current (already incremented) value of 'p'.

This is a valid implementation-specific technique (via the
"as-if" rule), provided p itself is not marked volatile.

That is, regardless whether the compiler turns:

save = p++;

into:

/* effective C code; and machine instructions */
save = p; /* add r1, 0, r2 */
p = p + 1; /* add r1, 1, r1 */

or:

p = p + 1; /* add r1, 1, r1 */
save = p - 1; /* add r1, -1, r2 */

the outcome is the same, as long as p is not "volatile". (And the
code runs just as fast either way, since both sequences use two
"add" instructions with embedded immediate constants; the only
difference is the value of those constants.)

If p *is* marked "volatile", however, the compiler cannot use the
second sequence, since that causes two reads from the object. (As
yet another wrinkle, "what constitutes an access" to one of these
things marked volatile "is implementation-defined", so if the
implementation can provide a particularly interesting interpretation,
it may actually be able to do the "add one, then re-read, then
subtract one" after all.)
Looks like a storm in a teacup. ['save' doesn't have to exist at all,
depending on the instruction set, and *p++=c; may execute in a single
instruction]
p++ has a value (old p) and a side effect (p = old p + 1).
*p++ dereferences the value of p++ (old p).
I'd care about implementation only when shopping for a compiler (or
squeezing out that last optimization)
Sorry, fail to see any mystery or flying eggs :)
Regards,
Ark
Jul 29 '06 #10
>Chris Torek wrote:
>>[the compiler can produce varying machine code for the C source:]
save = p++;
In article <r9******************************@comcast.com>,
Ark <ak*****@macroexpressions.comwrote:
>Looks like a storm in a teacup. ['save' doesn't have to exist at all,
depending on the instruction set,
The intent of this later example -- which I admit is not clear if
you follow the whole thread and think that it is *not* a separate
example -- is that the "save = p++;" is a complete line of C source
code. Hence "save" *does* exist, right there in the source code. :-)
>and *p++=c; may execute in a single instruction]
On some architectures (try it on a SPARC or MIPS!); but this is a
different line of source code anyway. :-) And of course, while a
number of architectures have a single instruction that implements
"*p++ = expr" and "*--p = expr", many of those do not have a single
instruction that implements "*++p = expr" or "*p-- = expr". (But
some do.)
>p++ has a value (old p) and a side effect (p = old p + 1).
*p++ dereferences the value of p++ (old p).
(Correct -- but can you say that in no fewer than 1000 words? :-) )
>I'd care about implementation only when shopping for a compiler (or
squeezing out that last optimization)
Indeed, this is an appropriate attitude.
--
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.
Jul 29 '06 #11
"neha" <ne*********@gmail.comwrote in message
news:11**********************@i42g2000cwa.googlegr oups.com...
Hi

My question is : Would the expression *p++=c be disallowed by the
complier.
The answer given in the book is: No.Because here even though the vlue
of p is acced twice it is used to modify two different objects p and
*p.
so can anyone explain this answer to me detail
Your question is similar to a FAQ, did you read it before posting?:

----------------------------------------------------
4.3: Does *p++ increment p, or what it points to?

A: Postfix ++ essentially has higher precedence than the prefix
unary operators. Therefore, *p++ is equivalent to *(p++); it
increments p, and returns the value which p pointed to before p
was incremented. To increment the value pointed to by p, use
(*p)++ (or perhaps ++*p, if the order of the side effect doesn't
matter).

References: K&R1 Sec. 5.1 p. 91; K&R2 Sec. 5.1 p. 95; ISO
Sec. 6.3.2, Sec. 6.3.3; H&S Sec. 7.4.4 pp. 192-3, Sec. 7.5 p.
193, Secs. 7.5.7,7.5.8 pp. 199-200.
----------------------------------------------------
A side point:
I would never rely on the compiler to reject a nonsense code fragment.
There are some types of problems that the compiler MUST issue a diagnostic
message for, but there are other things that are totally wrong but which the
compiler does not have to diagnose.
Aug 2 '06 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Francisco J. Reyes | last post by:
I get an Internal complier error when compiling C# windows project that uses a custom Class add as reference to the project. The problem appears to be related to the ENUM type used in the class...
3
by: Ygn | last post by:
#include <stdio.h> #include <winsock2.h> #include <windows.h> #include <process.h> #include <string.h> #include <winbase.h> #include <sys/socket.h> I would like to do compiling this header....
5
by: Seven Kast USA | last post by:
Hi pelase explain me complier design of c and i need a small example complier design all phases in c programming . by KAST
2
by: qbin_wang | last post by:
Hi: now i want to download a free c complier which can be used in windows system.and i see many posts in the comp.lang.c,but i don't find the answer.who can tell me the true and correct website...
2
by: Ali Alsaffar | last post by:
Hi there, - I updated my windows XP professional with all critical updates available at windowsupdate.com - I updated Microsoft .NET Framework 1.1.4322 from thier also - I installed Visual Basic...
8
by: shannon | last post by:
Hi there, Does anyone know if you can download a free javascript complier from the net. I need to check my code for a project. Thanks Shannon.
11
by: jryden | last post by:
I wrote the following code into a console program in Visual C++6. If you build a release build and select custom optimizations and select 'general optimizations' as the only optimization then you...
1
by: tccode97 | last post by:
Hi, I need an urgent help. I am developing a socket application in VC++ that uses asynchronous connnection. After doing search on google, I found the following link ...
16
by: sriever4u | last post by:
I am new to ARM linux, i am working on AT91RM9200 board and using ARM linuc C complier.. i want to know how to produce nanosecond delay using software...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.