strcpy question

M

mdh

I have a question about the library function strcpy.
In K&R on page 109, strcpy is used to copy a line ( line[] ) to a
pointer (char *), which is first allocated space by K&Rs "alloc"
function.
In a few pages prior to this, the example that K&R showed used this
definition for it's version of strcpy

void strcpy( char *s, char *t){

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

}

Could someone help me understand the library function, which,
according to the appendix, returns the target string.
So, in this case, what is passed to the library is an array-the
original string and a pointer to the target string? What happens if
the target pointer has not been allocated space? And, is this
acceptable ie to pass a pointer instead of an actual char array for
the target string?

tks
 
T

Tomás Ó hÉilidhe

void strcpy( char *s, char *t){

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

}

Could someone help me understand the library function, which,
according to the appendix, returns the target string.


Well firstly, this particular implementation of it does NOT return the
target string.

Let's take a look at that loop:

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

This is the same as the following:

for (;;) /* Eternal loop */
{
*s = *t;

++s;
++t;

if (!*(s-1)) break;
}

It copies the destination to the source, increments both pointers, and
finally checks to see whether the last character copied was the null
character. If so, the loop stops.

So, in this case, what is passed to the library is an array-the
original string  and a pointer to the target string? What happens if
the target pointer has not been allocated space? And, is this
acceptable ie to pass a pointer instead of an actual char array for
the target string?


If you have an array as follows:

char arr[16];

then when you write the name of the array on its own, what you have is
a pointer to the first element of the array, e.g.:

char arr[16];

char *p;

p = arr; /* Here we have a pointer to the first element */

(There are three special cases in which this isn't so:
1) When sizeof is applied to the array
2) When the addressof operator is applied to the array
3) ...I can't actually think of it off-hand, but I'm sure I'd know
it if I was presented with it.)

A pointer contains a memory address. When you invoke strcpy, you're
giving it two memory addresses, the address of the destination and the
address of the source. If the either pointer is dodgy, you'll get
undefined behaviour. For a pointer not to be dodgy, it must:
1) Point to memory that belongs to you, that is, memory that you're
allowed to access.
2) Point to a big enough chunk of memory to store what you want it to
store. If you go outside the boundary, you're writing to memory that
doesn't belong to you.
 
D

Default User

mdh said:
I have a question about the library function strcpy.
In K&R on page 109, strcpy is used to copy a line ( line[] ) to a
pointer (char *), which is first allocated space by K&Rs "alloc"
function.
In a few pages prior to this, the example that K&R showed used this
definition for it's version of strcpy

void strcpy( char *s, char *t){

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

}

Could someone help me understand the library function, which,
according to the appendix, returns the target string.

This says, perform the loop while the expression inside results in a
non-zero (true) value.

The express assign the currently pointed at value of t to the current
pointed-at element of s and increments both pointers. The result of the
expression is the character assigned to *s. So the copy ends when *t is
0, or the null terminator (end of string t).
So, in this case, what is passed to the library is an array-the
original string and a pointer to the target string? What happens if
the target pointer has not been allocated space?

Undefined behavior.
And, is this
acceptable ie to pass a pointer instead of an actual char array for
the target string?

You can't pass an array. In most contexts, the name of an array is
converted to a pointer to the first element. That's why both arguments
to strcpy() are pointers there.
 
M

mdh

Thanks all who replied. I did know that an address is passed to a
function when an array is passed as an argument, but I had not seen it
done like this, although it makes perfect sense.So, I guess that the
expectation of a function when getting an array as a parameter, is to
receive a pointer, no matter how the argument is formulated ( as an
array or pointer), with the exceptions ( of which I was unaware)
above. Thank you again.
 
T

Tomás Ó hÉilidhe

Thanks all who replied. I did know that an address is passed to a
function when an array is passed as an argument, but I had not seen it
done like this, although it makes perfect sense.So, I guess that the
expectation of a function when getting an array as a parameter, is to
receive a pointer, no matter how the argument is formulated ( as an
array or pointer), with the exceptions ( of which I was unaware)
above. Thank you again.


A function cannot take an array as a parameter. If you do the
following:

void Func(int arr[5])
{

}

Then it's EXACTLY the same as writing:

void Func(int *arr)
{

}

Try it out:

void Func(int arr[5])
{
int i;

arr = &i; /* arr is just a pointer to int */
}
 
M

mdh

A function cannot take an array as a parameter. If you do the
following:

 

Sorry if I was unclear...as this is what I was trying to say. In other
words, a function that **expects** an array, will in fact **actually**
receive a pointer as a parameter. So, what I was concentrating on was
the syntax where a pointer that had an array allocated to it ( ie was
not an array that had been converted to a pointer as an argument to a
function) is just as legal a construct under as passing an array
itself.
 
M

mdh

A function cannot take an array as a parameter. If you do the
following:


Sorry if I was unclear...as this is what I was trying to say. In
other
words, a function that **expects** an array, will in fact
**actually**
receive a pointer as a parameter. So, what I was concentrating on was
the syntax where a pointer that had an array allocated to it ( ie was
not an array that had been converted to a pointer as an argument to a
function) is just as legal a construct as passing an array
itself.
 
D

Default User

mdh said:
Sorry if I was unclear...as this is what I was trying to say. In other
words, a function that expects an array, will in fact actually
receive a pointer as a parameter.

A function does not and cannot "expect" an array. Even if you write the
declaration to look like an array to a human reading it, the function
expects nothing of the sort. It expects and receives a pointer.

void f(int p[50]);
void f(int p[1]);
void f(int *p);

The above are identical to the compiler.
So, what I was concentrating on was
the syntax where a pointer that had an array allocated to it ( ie was
not an array that had been converted to a pointer as an argument to a
function) is just as legal a construct under as passing an array
itself.

You can't pass an array, so yes they are equally valid.



Brian
 
K

Keith Thompson

mdh said:
Sorry if I was unclear...as this is what I was trying to say. In other
words, a function that **expects** an array, will in fact **actually**
receive a pointer as a parameter. So, what I was concentrating on was
the syntax where a pointer that had an array allocated to it ( ie was
not an array that had been converted to a pointer as an argument to a
function) is just as legal a construct under as passing an array
itself.

First, a point about terminology: a parameter is an object, local to a
function, declared in the function's declaration (for example argc and
argv in main()); an argument is an expression passed to a function in
a call.

There is no such thing in C as a function that expects an array.

A C function that *looks* like it expects an array argument, such as:
void foo(char arr[]) { /* whatever */ }
or even
void foo(char arr[42]) { /* whatever */ }
actually expects a pointer argument; both of the above is exactly
equivalent to:
void foo(char *arr) { /* whatever */ }

Using array *syntax* in a parameter declaration probably suggests that
the pointer argument should point to the first element of an array,
but any such suggestion has no more actual force than a comment.

The fact that C allows a parameter to be declared with array syntax,
and that such a parameter declaration is really no different from a
pointer parameter declaration, is IMHO unfortunate. It's mildly
convenient to be able to say that the argument is intended to be a
(converted) array, but the cost is increased confusion.

In a function call, it's not possible to have an expression of array
type as an argument. Any such expression will be converted to a
pointer, and the called function has absolutely no way of knowing
whether such a conversion has happened. (There are contexts in which
this conversion doesn't happen, but a function argument cannot be one
of those contexts.)
 
M

mdh

>....... Any such expression will be converted to a
pointer, and the called function has absolutely no way of knowing
whether such a conversion has happened. ....


Thanks Keith...that's what I thought, but just wanted to be sure.
In C, is it quite common to pass a pointer to which one has allocated
an array, as K&R do in this example?
 
K

Keith Thompson

mdh said:
Thanks Keith...that's what I thought, but just wanted to be sure.
In C, is it quite common to pass a pointer to which one has allocated
an array, as K&R do in this example?

Yes, it's extremely common; it's how arrays are usually dealt with in
C.

You also usually need some way to specify how big the array is, or how
big the portion you're interested in is. For strings, this is
generally determined by the position of the '\0' terminator. For
other arrays, it's common to pass a second argument that specifies the
length of the array (see, for example, the third parameter of
memcpy()).
 
D

David Thompson

On Mon, 5 May 2008 11:39:39 -0700 (PDT), Tomás Ó hÉilidhe
then when you write the name of [an] array on its own, what you have is
a pointer to the first element of the array, e.g.: <snip>
(There are three special cases in which this isn't so:
1) When sizeof is applied to the array
2) When the addressof operator is applied to the array
3) ...I can't actually think of it off-hand, but I'm sure I'd know
it if I was presented with it.)
Standard C has only (those) two explicit. C++ adds typeid, and initing
a reference (which includes passing to a reference parameter).

And C++ explicitly specifies cases where the expression is discarded:
full statement, cast to void, left of comma op; C instead makes those
'void expressions' whose 'value *or designator* is discarded'
(6.3.2.2, emphasis added) which implies that the lvalue-to-rvalue
conversion did not happen.

GNU C (the language compiled by GCC) adds typeof.

<snip rest>


- formerly david.thompson1 || achar(64) || worldnet.att.net
 
K

Keith Thompson

David Thompson said:
On Mon, 5 May 2008 11:39:39 -0700 (PDT), Tomás Ó hÉilidhe
then when you write the name of [an] array on its own, what you have is
a pointer to the first element of the array, e.g.: <snip>
(There are three special cases in which this isn't so:
1) When sizeof is applied to the array
2) When the addressof operator is applied to the array
3) ...I can't actually think of it off-hand, but I'm sure I'd know
it if I was presented with it.)
Standard C has only (those) two explicit. C++ adds typeid, and initing
a reference (which includes passing to a reference parameter).

C has three cases, only two of which can apply to array names. The
third case (in which an expression of array type is not implicitly
converted to a pointer to the array's first element) is a string
literal used in an initializer to initialize an array object.

[snip]
 

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
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top