Copying strings

K

Khookie

Hi everyone

Out of curiosity, would this be a valid implementation of a string
copy function?

int copy(char* to, char* from) {
while (*to++ = *from++);
}

It's just that, I notice in string.h that it makes the 'from' argument
a constant argument.

char *strcpy( char *to, const char *from );

Thus I suppose there needs to be some other pointer initialised to
walk the from string.

Is there a reason for this? I thought since the pointers are passed
by value to the function, you wouldn't need to need to worry about the
them being changed. Well, I thought you could save on the
initialisation of another pointer, but given my ignorance of the
language, I'm sure there's a good reason behind the const.

Sorry if it sounds terribly pedantic, I'm just interested in learning
why things are done a certain way.

Chris
 
D

Default User

Khookie said:
Hi everyone

Out of curiosity, would this be a valid implementation of a string
copy function?

int copy(char* to, char* from) {
while (*to++ = *from++);
}

It's just that, I notice in string.h that it makes the 'from' argument
a constant argument.

char *strcpy( char *to, const char *from );

Thus I suppose there needs to be some other pointer initialised to
walk the from string.

You are confused. That is a pointer to constant char, not a const
pointer to char. That is, the pointer can change, but not what it
points to.




Brian
 
B

Ben Pfaff

Khookie said:
Out of curiosity, would this be a valid implementation of a string
copy function?

int copy(char* to, char* from) {
while (*to++ = *from++);
}
Yes.

It's just that, I notice in string.h that it makes the 'from' argument
a constant argument.

I think that you are confusing "const char *" with "char* const".
In the former, the characters are const-qualified; in the latter,
the pointer is const-qualified.
 
P

pete

Khookie said:
Hi everyone

Out of curiosity, would this be a valid implementation of a string
copy function?

int copy(char* to, char* from) {
while (*to++ = *from++);
}

Your return type should be void instead of int.
 
K

Khookie

Your return type should be void instead of int.

ahh thanks everyone - I swore I got an error when compiling, but maybe
that was something else

void copy(char* to, const char* from) {
while (*to++ = *from++);
}
 
C

CBFalconer

Khookie said:
Out of curiosity, would this be a valid implementation of a string
copy function?

int copy(char* to, char* from) {
while (*to++ = *from++);
}

It's just that, I notice in string.h that it makes the 'from'
argument a constant argument.

char *strcpy( char *to, const char *from );

Thus I suppose there needs to be some other pointer initialised to
walk the from string.

That const applies to the string itself, not the pointer. It says
that strcpy will not modify the data pointed at by 'from'. This
often allows improved optimization. There is no need to modify
your code.
 
C

Chris Torek

Khookie wrote:
[with later correction applied][which is a valid implementation of "copy a string" a la strcpy(),
except of course for the different return-type and (lack of) value]

Others (including Chuck Falconer below) have noted the differences
between "const char *" and "char *const" and even "const char
*const" (as types)...

That const applies to the string itself, not the pointer. It says
that strcpy will not modify the data pointed at by 'from'.

Well, this promise is something of a phantom. In particular, you
(the C programmer writing C code, not the implementor of strcpy()
in this case) are allowed to "lie" about it, as it were:

void avoid_this_bad_code_practice(const int *p) {
*(int *)p = 42;
}
void call_the_bad_code(void) {
int x;

avoid_this_bad_code_practice(&x);
/* now x == 42 */
...
}

The behavior of this is well-defined, despite the "lie" about the
"const"-ness of *p in the first function. That is, the function
whose name tells you not to write it makes a promise ("won't change
*p") and then breaks it, in a way that the C Standard permits.
Because of this and other problems outlined below, the claim:
This often allows improved optimization.

is, I think, too strong. Careful and appropriate use of "const"
*sometimes* allows improved optimization, but not really "often".
In particular, rewriting copy() as:

void copy(char *to, const char *from) {
while (*to++ = *from++)
continue;
}

gives the compiler no additional optimization opportunities,
despite the addition of "const", because modifying to (for
any index i) is allowed to change from[j] (for any index j).
For instance:

void weird(void) {
char buf[12] = "hello";
copy(&buf[6], &buf[0]);
copy(&buf[0], &buf[1]);
puts(buf);
puts(buf + 6);
}

is well-defined, and must print "ello\nhello\n". (In this particular
case, if modifying *to changes a "future" *from that will affect
a "future" *to, the loop is unlikely to terminate at all, so the
issues are rather fuzzy here.)

More generally, a "const" qualifier prevents you from modifying
the object yourself through the specific lvalue given, but does
not prevent *other* modifications. It is perhaps easier to see
the effect with the following, which is not as bad as the "broken
promise" version:

#include <stdio.h>

int x = 42;

void pr(const int *p) {
printf("*p is %d\n", *p);
x++;
printf("*p is %d\n", *p);
}

int main(void) {
pr(&x);
return 0;
}

This program must print 42 and then 43 -- not 42 twice. The
"const"-ness of *p implies that pr() is not going to change *p,
and indeed it does not change *p by that name, but it *does*
change x, and *p happens to be an "alias" for x -- and the
C Standard requires that when x changes, *p change with it.
Therefore, "const" does *not* tell the compiler "this is not
going to change", and the compiler's optimizer cannot assume
that it does not change.

(C99's "restrict", combined with C89 "const", *does* make promises
like this, and can allow additional optimization. I believe
optimization was the main, or perhaps even sole, motivation for
adding "restrict".)
There is no need to modify your code.

This is of course true. :)
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top