*p++ = *q++ undefined? why?

C

CBFalconer

Eric said:
Even if p == q. (Confession: I very nearly made
the same mistake.)

Alright, modify the assumption to:

&p !- &q

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
P

pemo

pete said:
Michael said:
Vladimir S. Oka wrote:
Eric Sosman opined:
CBFalconer wrote:
pete wrote:

... snip ...

As long as (*p) is defined and (*q) is defined,
there is nothing wrong with (*p++ = *q++).

Assuming p != q.

Even if p == q. (Confession: I very nearly made
the same mistake.)

Now I can see it as well! Apologies for the confusion.

Now that I actually thought it through, isn't the above the very
construct K&R use to implement `strcpy()`? I left my copy at work, so
I can't look it up, but I'm pretty sure. Along the lines of:

while (*p++ = *q++)
;

Yes.
/* strcpy: copy t to s; pointer version 3 */
void strcpy(char *s, char *t)
{
while (*s++ = *t++)
;
}

You can see how that implementation of strcpy
would be undefined with something like:

char char_array[] = "xx\0";

strcpy(char_array, char_array + 1);

though

memmove(char_array, char_array + 1, 1 + strlen(char_array + 1));

would be fine.

Why? How? I cannot see anything undefined in that.
If you wrote "strcpy(char_array + 1, char_array);", then I would
agree.

That's what I meant write.

I must be going mad, or missing something here - are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}


int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}

If 'yes', can you explain why please.

while(*s++ = *t++)

As far as I can see, the assignment expression here will 'run' like
this:

1. eval *t

2. take value found in '1' - write to *s

3. increment s then t, OR, increment t then s.

4. repeat.
 
P

pete

pemo wrote:
I must be going mad, or missing something here - are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}

int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}

If 'yes', can you explain why please.

while(*s++ = *t++)

As far as I can see, the assignment expression here will 'run' like
this:

1. eval *t

2. take value found in '1' - write to *s

3. increment s then t, OR, increment t then s.

4. repeat.

When does the 'run' stop?
 
J

Joe Wright

pemo said:
pete said:
Michael said:
pete schrieb:
Vladimir S. Oka wrote:
Eric Sosman opined:
CBFalconer wrote:
pete wrote:

... snip ...

As long as (*p) is defined and (*q) is defined,
there is nothing wrong with (*p++ = *q++).
Assuming p != q.
Even if p == q. (Confession: I very nearly made
the same mistake.)
Now I can see it as well! Apologies for the confusion.

Now that I actually thought it through, isn't the above the very
construct K&R use to implement `strcpy()`? I left my copy at work, so
I can't look it up, but I'm pretty sure. Along the lines of:

while (*p++ = *q++)
;
Yes.
/* strcpy: copy t to s; pointer version 3 */
void strcpy(char *s, char *t)
{
while (*s++ = *t++)
;
}

You can see how that implementation of strcpy
would be undefined with something like:

char char_array[] = "xx\0";

strcpy(char_array, char_array + 1);

though

memmove(char_array, char_array + 1, 1 + strlen(char_array + 1));

would be fine.
Why? How? I cannot see anything undefined in that.
If you wrote "strcpy(char_array + 1, char_array);", then I would
agree.
That's what I meant write.

I must be going mad, or missing something here - are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}


int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}

If 'yes', can you explain why please.

while(*s++ = *t++)

As far as I can see, the assignment expression here will 'run' like
this:

1. eval *t

2. take value found in '1' - write to *s

3. increment s then t, OR, increment t then s.

4. repeat.
Because the destination of the assignment is within the source,
corrupting it.
 
P

pete

Joe said:
pemo wrote:
I must be going mad, or missing something here - are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}


int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}

If 'yes', can you explain why please.

while(*s++ = *t++)

As far as I can see, the assignment expression here will 'run' like
this:

1. eval *t

2. take value found in '1' - write to *s

3. increment s then t, OR, increment t then s.

4. repeat.
Because the destination of the assignment is within the source,
corrupting it.

Specifically, the null characters are being overwritten,
and the loop never ends.
 
P

pete

pete said:
Joe said:
pemo wrote:
I must be going mad, or missing something here
- are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}


int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}

If 'yes', can you explain why please.

while(*s++ = *t++)

As far as I can see,
the assignment expression here will 'run' like
this:

1. eval *t

2. take value found in '1' - write to *s

3. increment s then t, OR, increment t then s.

4. repeat.
Because the destination of the assignment is within the source,
corrupting it.

Specifically, the null characters are being overwritten,
and the loop never ends.

There's also a reserved identifier problem,
but that's another story.
 
S

stathis gotsis

blufox said:
didnt get this part

modify assumption to
&p !- &q
what is wrong in the "!= "?

Quote appropriate context when replying. As to your question, it was just a
typo.
 
B

Bas Wassink

pete said:
pete said:
Joe said:
pemo wrote:
I must be going mad, or missing something here
- are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}


int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}

If 'yes', can you explain why please.

while(*s++ = *t++)

As far as I can see,
the assignment expression here will 'run' like
this:

1. eval *t

2. take value found in '1' - write to *s

3. increment s then t, OR, increment t then s.

4. repeat.


Because the destination of the assignment is within the source,
corrupting it.

Specifically, the null characters are being overwritten,
and the loop never ends.


There's also a reserved identifier problem,
but that's another story.

From what I can see there's no UB here, since it's not the standard
library function strcpy, which is indeed said to behave undefined if the
objects overlap.
This function is (apart from using a reserved identifier) perfectly
valid. Even swapping the arguments would still make this code valid,
although the behaviour of the function might not be what one would want.

Bas
 
F

Flash Gordon

Bas said:
pete said:
pete said:
Joe Wright wrote:

pemo wrote:
I must be going mad, or missing something here
- are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}

int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}
There's also a reserved identifier problem,
but that's another story.

From what I can see there's no UB here, since it's not the standard
library function strcpy, which is indeed said to behave undefined if the
objects overlap.
This function is (apart from using a reserved identifier) perfectly
valid. Even swapping the arguments would still make this code valid,
although the behaviour of the function might not be what one would want.

If the overlap is the wrong way round the null termination gets
overwritten so the function does not stop at the end of the array and as
soon as it writes beyond the end of the array it has invoked UB.
 
P

pete

Bas said:
pete wrote:

From what I can see there's no UB here, since it's not the standard
library function strcpy,
which is indeed said to behave undefined if the
objects overlap.

If a C program defines a function named strcpy,
that cause undefined behavior.
That's what "reserved identifiers" is about.
Renaming the defined function as str_cpy,
would take care of the problem.
 
P

pete

pete said:
If a C program defines a function named strcpy,
that cause undefined behavior.
That's what "reserved identifiers" is about.
Renaming the defined function as str_cpy,
would take care of the problem.

After rereading your post,
I see that you acknowledged the reserved identifier problem.
Sorry about that.

Flash Gordon's reply to your post, was right.
 
P

pete

Bas said:
pete said:
Joe Wright wrote:

pemo wrote:

I must be going mad, or missing something here
- are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}


int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}

If 'yes', can you explain why please.

while(*s++ = *t++)

As far as I can see,
the assignment expression here will 'run' like
this:

1. eval *t

2. take value found in '1' - write to *s

3. increment s then t, OR, increment t then s.

4. repeat.


Because the destination of the assignment is within the source,
corrupting it.

Specifically, the null characters are being overwritten,
and the loop never ends.


There's also a reserved identifier problem,
but that's another story.

From what I can see there's no UB here, since it's not the standard
library function strcpy,
which is indeed said to behave undefined if the
objects overlap.
This function is (apart from using a reserved identifier) perfectly
valid. Even swapping the arguments would still make this code valid,
although the behaviour of the
function might not be what one would want.

Specifically, the null characters are being overwritten,
and the loop never ends.
The loop attempts to overwrite memory beyond the bounds
of the array, that's undefined behavior.

You can try running the program
if you feel like risking the consequences.
I've noticed that nobody has said
that they've run the program.
 
B

Bikram Bhatt

pete said:
pete said:
Joe said:
pemo wrote:
I must be going mad, or missing something here
- are you saying that
the code below gives UB?

#include <stdio.h>

void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}


int main(void)
{
char char_array[] = "xx\0";

strcpy(1 + char_array, char_array);

return 0;
}

If 'yes', can you explain why please.

while(*s++ = *t++)

As far as I can see,
the assignment expression here will 'run' like
this:

1. eval *t

2. take value found in '1' - write to *s

3. increment s then t, OR, increment t then s.

4. repeat.

Because the destination of the assignment is within the source,
corrupting it.

Specifically, the null characters are being overwritten,
and the loop never ends.

There's also a reserved identifier problem,
but that's another story.
What is that another story ? what is this resreved indentifier problem ?
 
B

Bas Wassink

pete said:
After rereading your post,
I see that you acknowledged the reserved identifier problem.
Sorry about that.

Flash Gordon's reply to your post, was right.

I realise I overlooked the overwriting of the '\0' at the end of the
string, however, I'm not sure about the reserved identifier problem now,
as the posted program did not include <string.h> and therefore does not
invade the implementations namespace by declaring a function called
'strcpy'.

I know using these standard library function names for personal
functions is a very bad idea, but I can't find anything in K&R2 or the
standard draft that says it's undefined behaviour. But I've probably not
looked hard enough as before..

Bas
 
F

Flash Gordon

Bas Wassink wrote:

I realise I overlooked the overwriting of the '\0' at the end of the
string, however, I'm not sure about the reserved identifier problem now,
as the posted program did not include <string.h> and therefore does not
invade the implementations namespace by declaring a function called
'strcpy'.

I know using these standard library function names for personal
functions is a very bad idea, but I can't find anything in K&R2 or the
standard draft that says it's undefined behaviour. But I've probably not
looked hard enough as before..

You've not looked hard enough. The identifier is always reserved for
external linkage whether or not the header is included, and the
implementation did not specify static so it was external linkage. From
n1124 section 7.13:
| — All identifiers with external linkage in any of the following
| subclauses (including the future library directions) are always
| reserved for use as identifiers with external linkage.157)
 
P

pete

Bas Wassink wrote:
I know using these standard library function names for personal
functions is a very bad idea, but I can't find anything in K&R2 or the
standard draft that says it's undefined behaviour.
But I've probably not
looked hard enough as before..

Search for these substrings:

"All external names described below are reserved
no matter what headers are included by the program"

"Function names that begin with str"
 
M

Micah Cowan

What is that another story ? what is this resreved indentifier problem ?

Please include only enough context to be necessary to understand your
reply.

The "reserved identifier problem" pete was referring to was the fact
that you can't just go around defining functions like strcpy() (whose
name is reserved to the implementation).
 
P

pete

Bikram said:
What is that another story ?
what is this resreved indentifier problem ?

N869
7.1.3 Reserved identifiers

[#2]
If the program declares or defines an identifier
in a context in which it is reserved
(other than as allowed by 7.1.4), or defines a
reserved identifier as a macro name,
the behavior is undefined.

7.26 Future library directions
[#1]
All external names described below
are reserved no matter what headers are included by the
program.

7.26.11 String handling <string.h>
[#1]
Function names that begin with str

I emphasise the "no matter what headers are included" part.
 

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

No members online now.

Forum statistics

Threads
474,176
Messages
2,570,950
Members
47,503
Latest member
supremedee

Latest Threads

Top