why do strcpy, strcat, & co return a pointer ?

C

cody

The order in which arguments are evaluated is undefined.
Unspecified: Multiple options are presented, one *must* be used.
Undefined: No constraints at all.

Thanks, I will remember it next time.
Because the claim was that the behavior is undefined. It's not clear how
different orders of evaluation for the parameters would lead to
undefined behavior.

I didn't claim that something would lead to undefined behaviour, I just said
that the order of parameter evaluation is undefined.
But you was right, in that example the order of parameter evaluation does
not make any difference (it would, when p would be an int instead of char*)
 
C

Christian Bau

It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

It does? Sorry, I don't get it.

Assuming you make it into a complete program:

#include <stdio.h>
#include <string.h>

int main(void)
{
char p[100] = "Fred";
printf("%s or %s\n", p, strcat(p, " and George"));
return 0;
}

What do you expect the first %s to print?

The order in which arguments are evaluated is undefined.

Correct (except that it is "unspecified"), and completely irrelevant.

What is the difference between undefined and unspecified? When I don't
specify or define something it is undefined/unspecified.[/QUOTE]

Both "undefined" and "unspecified" have very defined meanings in the C
Standard, and their meaning is different.
Note: I don't said "undefined behaviour" which is something completely
different.

And why is it irrelevant here? The output in the example depends on the
order of parameter evaluation.

No, it doesn't.
 
S

Simon Biber

Rouben Rostamian said:
Simon Biber said:
#include <stdio.h>
#include <string.h>

int main(void)
{
char p[100] = "Fred";
printf("%s or %s\n", p, strcat(p, " and George"));
return 0;
}

What do you expect the first %s to print?

I expect the first %s to print "Fred and George". By the time the
printf function is called, all side effects from the modification
of the array must be completed. I see no undefined behaviour,
it must print "Fred and George or Fred and George\n".

I see no problem evaluating p twice; its value does not change!
 
R

Rouben Rostamian

Rouben Rostamian said:
Simon Biber said:
#include <stdio.h>
#include <string.h>

int main(void)
{
char p[100] = "Fred";
printf("%s or %s\n", p, strcat(p, " and George"));
return 0;
}

What do you expect the first %s to print?

I expect the first %s to print "Fred and George". By the time the
printf function is called, all side effects from the modification
of the array must be completed. I see no undefined behaviour,
it must print "Fred and George or Fred and George\n".

I see no problem evaluating p twice; its value does not change!

You are quite right. I misspoke.
 
B

Barry Schwarz

It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

It does? Sorry, I don't get it.

Assuming you make it into a complete program:

#include <stdio.h>
#include <string.h>

int main(void)
{
char p[100] = "Fred";
printf("%s or %s\n", p, strcat(p, " and George"));
return 0;
}

What do you expect the first %s to print?

The order in which arguments are evaluated is undefined.

The order in which the arguments are evaluated is unspecified
behavior, but not undefined.


<<Remove the del for email>>
 
B

Barry Schwarz

CBFalconer said:
It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

Is it really undefined since there are implied sequence points at the
call to and return from strcat and p is only modified within strcat.


<<Remove the del for email>>
 
K

Kevin P. Fleming

Barry said:
Is it really undefined since there are implied sequence points at the
call to and return from strcat and p is only modified within strcat.

No, the point is that is p is _NOT_ modified, only the memory that p
points to is modified by strcat. Because of that, it doesn't matter
whether the contents of p (the address of the buffer) are evaluated
before or after the call to strcat, the buffer's address will not be
changed.
 
C

CBFalconer

Barry said:
Ben Pfaff said:
CBFalconer said:
It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

Is it really undefined since there are implied sequence points at the
call to and return from strcat and p is only modified within strcat.

In fact p is never modified. The storage at which p points IS
modified. Thus the action is well defined, but unexpected. I
think this is one of the few mistakes Ben has made.
 
B

Barry Schwarz

No, the point is that is p is _NOT_ modified, only the memory that p
points to is modified by strcat. Because of that, it doesn't matter
whether the contents of p (the address of the buffer) are evaluated
before or after the call to strcat, the buffer's address will not be
changed.

Since p is an array and not a pointer, p is being changed.


<<Remove the del for email>>
 
B

Barry Schwarz

Barry said:
Ben Pfaff said:
It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

Is it really undefined since there are implied sequence points at the
call to and return from strcat and p is only modified within strcat.

In fact p is never modified. The storage at which p points IS
modified. Thus the action is well defined, but unexpected. I
think this is one of the few mistakes Ben has made.
p is an array and not a pointer so p is being modified.

Since Ben didn't identify why he thought it was undefined behavior,
I'm still waiting for him to chime in.


<<Remove the del for email>>
 
K

Kevin Goodsell

Barry said:
Since p is an array and not a pointer, p is being changed.

In the statement given:

printf("%s or %s\n", p, strcat(p, " and George"));

p is an expression that evaluates to a pointer. In certain contexts, p
would evaluate to an array, but none of those contexts appear in the
example. As far as I can tell, the result is the same as if it had been
done this way:

char *tmp = p;
printf("%s or %s\n", tmp, strcat(tmp, " and George"));

-Kevin
 
I

Irrwahn Grausewitz

Barry Schwarz said:
Barry said:
It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

Is it really undefined since there are implied sequence points at the
call to and return from strcat and p is only modified within strcat.

In fact p is never modified. The storage at which p points IS
modified. Thus the action is well defined, but unexpected. I
think this is one of the few mistakes Ben has made.
p is an array and not a pointer so p is being modified.

Arrays are non-modifable lvalues, so p /cannot/ be modified. As
p in the example is used in value context, it is converted to a
pointer to its first element. This pointer isn't (and cannot be)
altered. What /is/ changed are the contents of the array (but it's
not the contents that are passed to printf). These contents are
inspected in the printf function after the arguments have been
evaluated, so the behaviour is well defined.

Consider Kevin's alteration of the example:

char p[100] = "Fred";
char *tmp = p;
printf("%s or %s\n", tmp, strcat(tmp, " and George"));

<snip>

Regards
 
D

Dan Pop

In said:
Barry said:
It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

Is it really undefined since there are implied sequence points at the
call to and return from strcat and p is only modified within strcat.

In fact p is never modified. The storage at which p points IS
modified. Thus the action is well defined, but unexpected. I
think this is one of the few mistakes Ben has made.
p is an array and not a pointer so p is being modified.

Yes, but it is modified between two well defined sequence points: the
one preceding the strcat call and the one preceding its return.

No undefined behaviour at all.
Since Ben didn't identify why he thought it was undefined behavior,
I'm still waiting for him to chime in.

To say what? That he goofed?

Dan
 
D

Dan Pop

In said:
Barry Schwarz said:
Barry Schwarz wrote:

It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

Is it really undefined since there are implied sequence points at the
call to and return from strcat and p is only modified within strcat.

In fact p is never modified. The storage at which p points IS
modified. Thus the action is well defined, but unexpected. I
think this is one of the few mistakes Ben has made.
p is an array and not a pointer so p is being modified.

Arrays are non-modifable lvalues, so p /cannot/ be modified.

Of course it can, just not via direct assignment:

p[0] = 'B';

does modify the p object, which is an array of 100 characters.

Dan
 
I

Irrwahn Grausewitz

In <[email protected]> Irrwahn Grausewitz <[email protected]> writes:
Arrays are non-modifable lvalues, so p /cannot/ be modified.

Of course it can, just not via direct assignment:

p[0] = 'B';

does modify the p object, which is an array of 100 characters.

Hrmpf. Maybe I should have written: "It is impossible to modify
the pointer p is converted to when used in a value context."

However, to someone with *both* cerebral hemispheres enabled the
meaning of my original claim should've been clear from the context,
which you snipped. ;^)

[unsnip]
IG> As p in the example is used in value context, it is converted to
IG> a pointer to its first element. This pointer isn't (and cannot
IG> be) altered. What /is/ changed are the contents of the array
IG> (but it's not the contents that are passed to printf).

Regards
 
D

Dan Pop

In said:
[email protected] (Dan Pop) said:
In <[email protected]> Irrwahn Grausewitz <[email protected]> writes:
Arrays are non-modifable lvalues, so p /cannot/ be modified.

Of course it can, just not via direct assignment:

p[0] = 'B';

does modify the p object, which is an array of 100 characters.

Hrmpf. Maybe I should have written: "It is impossible to modify
the pointer p is converted to when used in a value context."

However, to someone with *both* cerebral hemispheres enabled the
meaning of my original claim should've been clear from the context,
which you snipped. ;^)

[unsnip]
IG> As p in the example is used in value context, it is converted to
IG> a pointer to its first element. This pointer isn't (and cannot
IG> be) altered. What /is/ changed are the contents of the array
IG> (but it's not the contents that are passed to printf).

The context doesn't make your statement any less wrong. And the general
context of the discussion was the p *object* (which does get changed in
the code under discussion), not the pointer p decays to when used
in a value context.

Dan
 
I

Irrwahn Grausewitz

In said:
[email protected] (Dan Pop) said:
In <[email protected]> Irrwahn Grausewitz <[email protected]> writes:
Arrays are non-modifable lvalues, so p /cannot/ be modified.

Of course it can, just not via direct assignment:

p[0] = 'B';

does modify the p object, which is an array of 100 characters.

Hrmpf. Maybe I should have written: "It is impossible to modify
the pointer p is converted to when used in a value context."

However, to someone with *both* cerebral hemispheres enabled the
meaning of my original claim should've been clear from the context,
which you snipped. ;^)

[unsnip]
IG> As p in the example is used in value context, it is converted to
IG> a pointer to its first element. This pointer isn't (and cannot
IG> be) altered. What /is/ changed are the contents of the array
IG> (but it's not the contents that are passed to printf).

The context doesn't make your statement any less wrong.
Maybe we could agree that the wording was wrong, and it didn't
express what I wanted to say.
And the general
context of the discussion was the p *object* (which does get changed in
the code under discussion), not the pointer p decays to when used
in a value context.

Well, right. And since the changes to the object designated by p
are completed before pointers to the first byte of that object are
passed to printf, the construct in question upthread is well defined
in terms of C.

Regards
 
C

CBFalconer

Dan said:
Irrwahn Grausewitz said:
[email protected] (Dan Pop) said:
Arrays are non-modifable lvalues, so p /cannot/ be modified.

Of course it can, just not via direct assignment:

p[0] = 'B';

does modify the p object, which is an array of 100 characters.

Hrmpf. Maybe I should have written: "It is impossible to modify
the pointer p is converted to when used in a value context."

However, to someone with *both* cerebral hemispheres enabled the
meaning of my original claim should've been clear from the context,
which you snipped. ;^)

[unsnip]
IG> As p in the example is used in value context, it is converted
IG> to a pointer to its first element. This pointer isn't (and
IG> cannot be) altered. What /is/ changed are the contents of the
IG> array (but it's not the contents that are passed to printf).

The context doesn't make your statement any less wrong. And the
general context of the discussion was the p *object* (which does
get changed in the code under discussion), not the pointer p
decays to when used in a value context.

No - see subject. The context is functions returning extraneous
pointers and the misuse and confusion that can result from using
such, with a side trip into the legitimacy of the example confused
code.
 
B

Barry Schwarz

In the statement given:

printf("%s or %s\n", p, strcat(p, " and George"));

p is an expression that evaluates to a pointer. In certain contexts, p
would evaluate to an array, but none of those contexts appear in the

I agree that p evaluates to a pointer in the statement but, after
strcat has returned, the actual contents of p have been modified.
example. As far as I can tell, the result is the same as if it had been
done this way:

char *tmp = p;
printf("%s or %s\n", tmp, strcat(tmp, " and George"));

The one difference is that the contents of tmp have not been modified.



<<Remove the del for email>>
 
B

Barry Schwarz

Barry Schwarz said:
Barry Schwarz wrote:

It allows you to be baffled by the peculiar run-time actions of:

char p[100] = "Fred";
....
printf("%s or %s\n", p, strcat(p, " and George"));

That code has undefined behavior, you know.

Is it really undefined since there are implied sequence points at the
call to and return from strcat and p is only modified within strcat.

In fact p is never modified. The storage at which p points IS
modified. Thus the action is well defined, but unexpected. I
think this is one of the few mistakes Ben has made.
p is an array and not a pointer so p is being modified.

Arrays are non-modifable lvalues, so p /cannot/ be modified. As

Non-modifiable lvalues cannot be modified by an assignment statement
but arrays are objects and certainly can be modified. In fact, after
strcat returns, the contents of the array p have been modified.
p in the example is used in value context, it is converted to a
pointer to its first element. This pointer isn't (and cannot be)
altered. What /is/ changed are the contents of the array (but it's
not the contents that are passed to printf). These contents are

No disagreement.
inspected in the printf function after the arguments have been
evaluated, so the behaviour is well defined.

I don't disagree but I'm still waiting for Ben to tell us what
prompted his original comment.
Consider Kevin's alteration of the example:

char p[100] = "Fred";
char *tmp = p;
printf("%s or %s\n", tmp, strcat(tmp, " and George"));

<snip>

Regards



<<Remove the del for email>>
 

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
474,102
Messages
2,570,645
Members
47,247
Latest member
GabrieleL2

Latest Threads

Top