Simultaneous read and write on a variable in C++

N

Novice Coder

Here is the code

int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}

Is the behaviour of this code undefined in C++?
 
V

Victor Bazarov

Here is the code

int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}

Is the behaviour of this code undefined in C++?

Yes, AFAIK. There is no intervening sequence point between the
assignment and indexing. Even though there are parentheses, it is not
guaranteed that the compiler isn't going to "optimize" it and use the
previous value of 'p' (undefined) for dereferencing it. If you need to
introduce a sequence point, use the comma:

p=a,p[0]; // no problem

V
 
S

SG

Here is the code

int main()
{
    char *p;
    char a[]={"Hello"};
    (p=a)[0]; // This line
    return 0;
}

Is the behaviour of this code undefined in C++?

No. The assignment is done which yields the new pointer value itself
which is then dereferenced. No problem at all.

Cheers!
SG
 
C

Calum

Here is the code

int main()
{
    char *p;
    char a[]={"Hello"};
    (p=a)[0]; // This line
    return 0;

}

Is the behaviour of this code undefined in C++?

Looks fine to me. It's fairly common (especially in C) to combine an
assignment and an evaluation into the same expression. (p=a) will
always evaluate to a, no undefined behaviour in sight. You might come
across code like

while( (ch=fgetc(fp))!=-1 )
{
}

The only problem would be if you attempted to use p before the next
sequence point. E.g.

(p=a)+a // Ok
(p=a)+(p=b) // Undefined
(p=a)+p // Undefined
 
P

Prasoon Saurav

Here is the code

int main()
{
    char *p;
    char a[]={"Hello"};
    (p=a)[0]; // This line
    return 0;

}

Is the behaviour of this code undefined in C++?

(p=a)[0]; is UB . The side effect of the assignment operation is
guaranteed to be complete only after we reach a sequence point i.e ' ;
'. In this case the access is made prior to the side effect
completion. The is no total ordering between the assignment and the
dereference

The result of (a=b) is the lvalue 'a' with its rvalue as b, so its 'a'
which is getting accessed and that too before the next sequence point.
Noone can guarantee that the side effect of (a=b) is complete when we
dereference 'a' or the result of (a=b) i.e the lvalue a itself.

HTH
Prasoon
 
P

Prasoon Saurav

Here is the code
int main()
{
     char *p;
     char a[]={"Hello"};
     (p=a)[0]; // This line
     return 0;
}
Is the behaviour of this code undefined in C++?

I vote that it is not UB.

(p=a)[0] is equivalent to *(p=a); if *(p=a) is UB then surely *(p2++) is
also UB?  Clearly nonsense. (p=a)[0] + (p=a+1)[0] is UB however.

/Leigh

*(p2++) isn't UB. p++ evaluates to 'p'(a copy) because the result of
post increment is the "value"(old) of the operand. In (p=a) the access/
dereference is on p (lvalue) itself and not on a copy of 'p'.

Assignment operation is defined in section 5.17

"The result of the assignment operation is the value stored in the
left operand after the assignment has taken place; the result
is an lvalue."

This is very confusing. :p

HTH
Prasoon
 
P

Prasoon Saurav

Here is the code
int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}
Is the behaviour of this code undefined in C++?
I vote that it is not UB.
(p=a)[0] is equivalent to *(p=a); if *(p=a) is UB then surely *(p2++) is
also UB? Clearly nonsense. (p=a)[0] + (p=a+1)[0] is UB however.

I meant '*(++p2)' not '*(p2++)'.

/Leigh

Yes I believe *(++p2) is UB too.
 
P

Prasoon Saurav

On 12/01/2012 12:50, Leigh Johnston wrote:
On 11/01/2012 17:08, Novice Coder wrote:
Here is the code
int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}
Is the behaviour of this code undefined in C++?
I vote that it is not UB.
(p=a)[0] is equivalent to *(p=a); if *(p=a) is UB then surely *(p2++) is
also UB? Clearly nonsense. (p=a)[0] + (p=a+1)[0] is UB however.
I meant '*(++p2)' not '*(p2++)'.
/Leigh
Yes I believe *(++p2) is UB too.

Bullshit; are you trolling?

/Leigh

Huh?
 
J

Juha Nieminen

Prasoon Saurav said:

Don't worry. He's one of those people who seem to think that
"trolling" means "disagrees with me" (and mostly uses it as an
insult).
 
F

Fred Zwarts \(KVI\)

"Prasoon Saurav" wrote in message
...

The result of (a=b) is the lvalue 'a' with its rvalue as b, so its 'a'
which is getting accessed and that too before the next sequence point.
Noone can guarantee that the side effect of (a=b) is complete when we
dereference 'a' or the result of (a=b) i.e the lvalue a itself.

Does that mean that a=(b=c) is also UB?
 
G

gwowen

Is the behaviour of this code undefined in C++?

(p=a)[0]; is UB . The side effect of the assignment operation is
guaranteed to be complete only after we reach a sequence point i.e ' ;
'.

You're not deferencing p, you're dereferencing the result of (p=a)
which is (unambiguously) a.
 
P

Prasoon Saurav

(p=a)[0]; is UB . The side effect of the assignment operation is
guaranteed to be complete only after we reach a sequence point i.e ' ;
'.

You're not deferencing p, you're dereferencing the result of (p=a)
which is (unambiguously) a.

The result of (p=a) is lvalue 'p' with its rvalue 'a'.
 
P

Prasoon Saurav

"Prasoon Saurav"  wrote in message






Does that mean that a=(b=c) is also UB?

This is what the FAQ says "If an object is written to within a full
expression, any and all accesses to it within the same expression must
be directly involved in the computation of the value to be written."

This expression satisfies that condition so it is well defined.
 
V

Victor Bazarov

Here is the code

int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}

Is the behaviour of this code undefined in C++?

Yes, AFAIK. There is no intervening sequence point between the
assignment and indexing. Even though there are parentheses, it is not
guaranteed that the compiler isn't going to "optimize" it and use the
previous value of 'p' (undefined) for dereferencing it.

I think now that I was wrong there. The expression in parentheses has
the value the same as 'a', and *that* is used to dereference the pointer
(the indexing is adding the index and then dereferencing). The relevant
portion of the Standard (using the latest Draft):

<<The assignment operator (=) and the compound assignment operators all
group right-to-left. All require a modifiable lvalue as their left
operand and return an lvalue referring to the left operand. The result
in all cases is a bit-field if the left operand is a bit-field. In all
cases, the assignment is sequenced after the value computation of the
right and left operands, and before the value computation of the
assignment expression.>>

The last sentence is important, I believe. "Sequenced" is the key word.
If you need to
introduce a sequence point, use the comma:

p=a,p[0]; // no problem

V

V
 
P

Prasoon Saurav

Here is the code
int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}
Is the behaviour of this code undefined in C++?
Yes, AFAIK. There is no intervening sequence point between the
assignment and indexing. Even though there are parentheses, it is not
guaranteed that the compiler isn't going to "optimize" it and use the
previous value of 'p' (undefined) for dereferencing it.

I think now that I was wrong there.  The expression in parentheses has
the value the same as 'a', and *that* is used to dereference the pointer
(the indexing is adding the index and then dereferencing).  The relevant
portion of the Standard (using the latest Draft):

<<The assignment operator (=) and the compound assignment operators all
group right-to-left. All require a modifiable lvalue as their left
operand and return an lvalue referring to the left operand. The result
in all cases is a bit-field if the left operand is a bit-field. In all
cases, the assignment is sequenced after the value computation of the
right and left operands, and before the value computation of the
assignment expression.>>

The last sentence is important, I believe.  "Sequenced" is the key word..

 > If you need to
introduce a sequence point, use the comma:
p=a,p[0]; // no problem

V

The term sequenced before/after and value computation are part of C+
+11 and not of C++03. In C++11 the expression has well defined
behavior. In C++03 it is not.

P.S
 
P

Prasoon Saurav

On 1/11/2012 12:28 PM, Victor Bazarov wrote:
On 1/11/2012 12:08 PM, Novice Coder wrote:
Here is the code
int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}
Is the behaviour of this code undefined in C++?
Yes, AFAIK. There is no intervening sequence point between the
assignment and indexing. Even though there are parentheses, it is not
guaranteed that the compiler isn't going to "optimize" it and use the
previous value of 'p' (undefined) for dereferencing it.
I think now that I was wrong there.  The expression in parentheses has
the value the same as 'a', and *that* is used to dereference the pointer
(the indexing is adding the index and then dereferencing).  The relevant
portion of the Standard (using the latest Draft):
<<The assignment operator (=) and the compound assignment operators all
group right-to-left. All require a modifiable lvalue as their left
operand and return an lvalue referring to the left operand. The result
in all cases is a bit-field if the left operand is a bit-field. In all
cases, the assignment is sequenced after the value computation of the
right and left operands, and before the value computation of the
assignment expression.>>
The last sentence is important, I believe.  "Sequenced" is the key word.
  >  If you need to
introduce a sequence point, use the comma:
p=a,p[0]; // no problem
V
V
The term sequenced before/after and value computation are part of C+
+11 and not of C++03. In C++11 the expression has well defined
behavior. In C++03 it is not.

Nonsense.

(p=a)[0] is perfectly fine in C++03 as is *(p=a) as is *++p2; you are
confusing this defined behaviour with ((p=a)[0] + (p=a+1)[0]) which is UB.

/Leigh

Instead of using words like "bullshit", "nonsense" why don't you take
help of the Standard to prove yourself correct. Which statement of
mine do you think is incorrect and why? If you have some counter-
argument please make it.

P.S
 
P

Prasoon Saurav

On 12/01/2012 18:11, Prasoon Saurav wrote:
On 1/11/2012 12:28 PM, Victor Bazarov wrote:
On 1/11/2012 12:08 PM, Novice Coder wrote:
Here is the code
int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}
Is the behaviour of this code undefined in C++?
Yes, AFAIK. There is no intervening sequence point between the
assignment and indexing. Even though there are parentheses, it is not
guaranteed that the compiler isn't going to "optimize" it and use the
previous value of 'p' (undefined) for dereferencing it.
I think now that I was wrong there.  The expression in parentheseshas
the value the same as 'a', and *that* is used to dereference the pointer
(the indexing is adding the index and then dereferencing).  The relevant
portion of the Standard (using the latest Draft):
<<The assignment operator (=) and the compound assignment operators all
group right-to-left. All require a modifiable lvalue as their left
operand and return an lvalue referring to the left operand. The result
in all cases is a bit-field if the left operand is a bit-field. In all
cases, the assignment is sequenced after the value computation of the
right and left operands, and before the value computation of the
assignment expression.>>
The last sentence is important, I believe.  "Sequenced" is the keyword.
   >    If you need to
introduce a sequence point, use the comma:
p=a,p[0]; // no problem
V
V
--
I do not respond to top-posted replies, please don't ask
The term sequenced before/after and value computation are part of C+
+11 and not of C++03. In C++11 the expression has well defined
behavior. In C++03 it is not.
Nonsense.
(p=a)[0] is perfectly fine in C++03 as is *(p=a) as is *++p2; you are
confusing this defined behaviour with ((p=a)[0] + (p=a+1)[0]) which is UB.
/Leigh
Instead of using words like "bullshit", "nonsense" why don't you take
help of the Standard to prove yourself correct. Which statement of
mine do you think is incorrect and why? If you have some counter-
argument please make it.

You said '*--p' is UB which disagrees with the draft standard:

24.4.1/5
"...
*first++ = *--last;
..."

So you clearly do not know what you are talking about in this area and I
still suspect you of being a troll.

/Leigh

Which draft are you quoting from, n3290? Each of my comment is from C+
+03 point of view. In C++11 *++p; is well defined. I am still not sure
whether it is well defined in C++03
See my this answer : http://stackoverflow.com/a/4183735/165520
 
P

Prasoon Saurav

On 12/01/2012 18:11, Prasoon Saurav wrote:
On 1/11/2012 12:28 PM, Victor Bazarov wrote:
On 1/11/2012 12:08 PM, Novice Coder wrote:
Here is the code
int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}
Is the behaviour of this code undefined in C++?
Yes, AFAIK. There is no intervening sequence point between the
assignment and indexing. Even though there are parentheses, it is not
guaranteed that the compiler isn't going to "optimize" it and use the
previous value of 'p' (undefined) for dereferencing it.
I think now that I was wrong there.  The expression in parentheseshas
the value the same as 'a', and *that* is used to dereference the pointer
(the indexing is adding the index and then dereferencing).  The relevant
portion of the Standard (using the latest Draft):
<<The assignment operator (=) and the compound assignment operators all
group right-to-left. All require a modifiable lvalue as their left
operand and return an lvalue referring to the left operand. The result
in all cases is a bit-field if the left operand is a bit-field. In all
cases, the assignment is sequenced after the value computation of the
right and left operands, and before the value computation of the
assignment expression.>>
The last sentence is important, I believe.  "Sequenced" is the keyword.
   >    If you need to
introduce a sequence point, use the comma:
p=a,p[0]; // no problem
V
V
--
I do not respond to top-posted replies, please don't ask
The term sequenced before/after and value computation are part of C+
+11 and not of C++03. In C++11 the expression has well defined
behavior. In C++03 it is not.
Nonsense.
(p=a)[0] is perfectly fine in C++03 as is *(p=a) as is *++p2; you are
confusing this defined behaviour with ((p=a)[0] + (p=a+1)[0]) which is UB.
/Leigh
Instead of using words like "bullshit", "nonsense" why don't you take
help of the Standard to prove yourself correct. Which statement of
mine do you think is incorrect and why? If you have some counter-
argument please make it.

You said '*--p' is UB which disagrees with the draft standard:

24.4.1/5
"...
*first++ = *--last;
..."

So you clearly do not know what you are talking about in this area and I
still suspect you of being a troll.

/Leigh

One more thing whether *--p; invokes UB or not depends on whether 'p'
is a user defined type or not.


C++03

*--p; if p is a user defined type with overloaded -- and * then the
behavior is well defined (function calls introduce sequence points).
For primitive types like what we have in the opening post the behavior
is undefined.

P.S
 
P

Prasoon Saurav

On 12/01/2012 18:11, Prasoon Saurav wrote:
On 1/11/2012 12:28 PM, Victor Bazarov wrote:
On 1/11/2012 12:08 PM, Novice Coder wrote:
The term sequenced before/after and value computation are part of C+
+11 and not of C++03. In C++11 the expression has well defined
behavior. In C++03 it is not.
Nonsense.
(p=a)[0] is perfectly fine in C++03 as is *(p=a) as is *++p2; youare
confusing this defined behaviour with ((p=a)[0] + (p=a+1)[0]) which
is UB.
/Leigh
Instead of using words like "bullshit", "nonsense" why don't you take
help of the Standard to prove yourself correct. Which statement of
mine do you think is incorrect and why? If you have some counter-
argument please make it.
You said '*--p' is UB which disagrees with the draft standard:
24.4.1/5
"...
*first++ = *--last;
..."
So you clearly do not know what you are talking about in this area and I
still suspect you of being a troll.

And if you claim again that this is a fix in C++11 here is a very old
line of code from "The C Programming Language":

5.5
"
val = *--p; /* pop top of stack into val */
"

So again you clearly do not know what you are talking about.

/Leigh

So let me tell you what I have been talking so far. In C the behavior
is well defined because the result of '--' is an rvalue. In C++03 the
behavior is undefined, I have given the reason why. In C++11 the
behavior is well defined (refer to my stackoverflow answer).
 
P

Prasoon Saurav

On 12/01/2012 19:18, Prasoon Saurav wrote:
On 12/01/2012 18:11, Prasoon Saurav wrote:
On 1/11/2012 12:28 PM, Victor Bazarov wrote:
On 1/11/2012 12:08 PM, Novice Coder wrote:
Here is the code
int main()
{
char *p;
char a[]={"Hello"};
(p=a)[0]; // This line
return 0;
}
Is the behaviour of this code undefined in C++?
Yes, AFAIK. There is no intervening sequence point between the
assignment and indexing. Even though there are parentheses, it isnot
guaranteed that the compiler isn't going to "optimize" it and usethe
previous value of 'p' (undefined) for dereferencing it.
I think now that I was wrong there.  The expression in parentheses has
the value the same as 'a', and *that* is used to dereference the pointer
(the indexing is adding the index and then dereferencing).  The relevant
portion of the Standard (using the latest Draft):
<<The assignment operator (=) and the compound assignment operators all
group right-to-left. All require a modifiable lvalue as their left
operand and return an lvalue referring to the left operand. The result
in all cases is a bit-field if the left operand is a bit-field. Inall
cases, the assignment is sequenced after the value computation of the
right and left operands, and before the value computation of the
assignment expression.>>
The last sentence is important, I believe.  "Sequenced" is the key word.
    >      If you need to
introduce a sequence point, use the comma:
p=a,p[0]; // no problem
V
V
--
I do not respond to top-posted replies, please don't ask
The term sequenced before/after and value computation are part of C+
+11 and not of C++03. In C++11 the expression has well defined
behavior. In C++03 it is not.
Nonsense.
(p=a)[0] is perfectly fine in C++03 as is *(p=a) as is *++p2; you are
confusing this defined behaviour with ((p=a)[0] + (p=a+1)[0]) which is UB.
/Leigh
Instead of using words like "bullshit", "nonsense" why don't you take
help of the Standard to prove yourself correct. Which statement of
mine do you think is incorrect and why? If you have some counter-
argument please make it.
You said '*--p' is UB which disagrees with the draft standard:
24.4.1/5
"...
*first++ = *--last;
..."
So you clearly do not know what you are talking about in this area andI
still suspect you of being a troll.
/Leigh
Which draft are you quoting from, n3290? Each of my comment is from C+
+03 point of view. In C++11 *++p; is well defined. I am still not sure
whether it is well defined in C++03
See my this answer :http://stackoverflow.com/a/4183735/165520

You are so wrong that if your wrongness had mass it would have a massive
event horizon; see my answer follow-up else-thread and then admit you
are wrong.

/Leigh


LOL.
If *++p is well defined you might argue ++p =10; (for some int 'p') is
also well defined. :p

P.S
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top