Confused by a c-faq example

  • Thread starter Schraalhans Keukenmeester
  • Start date
S

Schraalhans Keukenmeester

According to www.c-faq.com (Q6.6)

--------
Q: If you can't assign to arrays, then how can

int f(char str[])
{
if(str[0] == '\0')
str = "none";
...
}

work?

A: In this code, str is a function parameter, so its declaration is
rewritten by the compiler as described in question 6.4. In other words,
str is a pointer (of type char *), and it is legal to assign to it.

----------

I see the logic why a value can be assigned to str in the function, but
would there be any point in doing so ? Am I wrong when I think the
passed array never gets the assigned value when the function returns?
Or am I missing something here ? (Tried the example in C99 mode as well
as C89) mystr[]'s value has not changed after:

char mystr[10];
mystr[0]='\0';
f(mystr);
printf("%s\n",mystr);

I have sofar always used strcpy in cases like this, but now I am in
doubt whether I overlooked something...

Thanks in advance.
Sh
 
C

Christopher Benson-Manica

(WRT FAQ 6.6)
I see the logic why a value can be assigned to str in the function, but
would there be any point in doing so ? Am I wrong when I think the
passed array never gets the assigned value when the function returns?

You are not wrong; function arguments are always passed by value.
The only thing assigning directly to a function argument is likely to
accomplish is possibly saving you a variable declaration.
 
R

Richard

According to www.c-faq.com (Q6.6)

--------
Q: If you can't assign to arrays, then how can

int f(char str[])
{
if(str[0] == '\0')
str = "none";
...
}

work?

A: In this code, str is a function parameter, so its declaration is
rewritten by the compiler as described in question 6.4. In other words,
str is a pointer (of type char *), and it is legal to assign to it.

----------

I see the logic why a value can be assigned to str in the function, but
would there be any point in doing so ? Am I wrong when I think the
passed array never gets the assigned value when the function returns?

No you are not wrong. You are misunderstanding the reason its done as it
is above. It is only to show that there are cases where arrays can be
reassigned - in function calls where the compiler treats the parameter
as a char *. The pointer is being rewritten : not the contents of what
it originally pointed to.

A good text is "Expert C programming" by Van Der Linden - very
accessible. It spends a lot of time clarying something that many
programmers think they understand but dont at the end of the day. It is
confusing.

best of luck!

Or am I missing something here ? (Tried the example in C99 mode as well
as C89) mystr[]'s value has not changed after:

char mystr[10];
mystr[0]='\0';
f(mystr);
printf("%s\n",mystr);

I have sofar always used strcpy in cases like this, but now I am in
doubt whether I overlooked something...

Thanks in advance.
Sh
 
C

Chris Torek

According to www.c-faq.com (Q6.6)
int f(char str[])
{
if(str[0] == '\0')
str = "none";
...
} [snippage]
I see the logic why a value can be assigned to str in the function, but
would there be any point in doing so ? Am I wrong when I think the
passed array never gets the assigned value when the function returns?

You are correct about this, as others have noted.

As for why one might write f() as shown above ... well, consider
the following minor rewrite (to make "str" obviously a pointer)
with a partial expansion of the "...":

/*
* Perform various transformations. If the argument is "none"
* or "", the transformation is just a copy.
*/
int f(char *str) {
if (str[0] == '\0')
str = "none";
printf("please wait, doing <%s> transformation\n", str);
... big nested loop ...
...
if (strcmp(str, "none") != 0)
... do some extra work ...
...
...
...
}

Without the assignment, this prints "doing <> transformation"; with
it, it prints "doing <none> transformation" (assuming str is an empty
string). Then, inside the nested loop, a single strcmp() against
"none" suffices. Without the assignment to "str", we might have
to write this as:

int f(char *str) {
printf("please wait, doing <%s> transformation\n",
str[0] ? str : "none");
... big nested loop ...
...
if (strcmp(str, "") != 0 && strcmp(str, "none") != 0)
... do some extra work ...
...
...
...
}

(or similar). So changing the local variable "str", without changing
the caller's array, is sometimes a convenient way to reduce the
number of cases that must be handled inside the function.
 
K

Keith Thompson

Richard said:
Schraalhans Keukenmeester said:
According to www.c-faq.com (Q6.6)

--------
Q: If you can't assign to arrays, then how can

int f(char str[])
{
if(str[0] == '\0')
str = "none";
...
}

work?

A: In this code, str is a function parameter, so its declaration is
rewritten by the compiler as described in question 6.4. In other words,
str is a pointer (of type char *), and it is legal to assign to it.

----------

I see the logic why a value can be assigned to str in the function, but
would there be any point in doing so ? Am I wrong when I think the
passed array never gets the assigned value when the function returns?

No you are not wrong. You are misunderstanding the reason its done as it
is above. It is only to show that there are cases where arrays can be
reassigned - in function calls where the compiler treats the parameter
as a char *. The pointer is being rewritten : not the contents of what
it originally pointed to.
[...]

This is not a case where an array can be reassigned. It's a case
where something whose declaration *looks like* an array declaration
can be reassigned. str is a pointer, not an array.
 
R

Richard

Keith Thompson said:
Richard said:
Schraalhans Keukenmeester said:
According to www.c-faq.com (Q6.6)

--------
Q: If you can't assign to arrays, then how can

int f(char str[])
{
if(str[0] == '\0')
str = "none";
...
}

work?

A: In this code, str is a function parameter, so its declaration is
rewritten by the compiler as described in question 6.4. In other words,
str is a pointer (of type char *), and it is legal to assign to it.

----------

I see the logic why a value can be assigned to str in the function, but
would there be any point in doing so ? Am I wrong when I think the
passed array never gets the assigned value when the function returns?

No you are not wrong. You are misunderstanding the reason its done as it
is above. It is only to show that there are cases where arrays can be
reassigned - in function calls where the compiler treats the parameter
as a char *. The pointer is being rewritten : not the contents of what
it originally pointed to.
[...]

This is not a case where an array can be reassigned. It's a case
where something whose declaration *looks like* an array declaration
can be reassigned. str is a pointer, not an array.

Isn't that what I said? Maybe my terminology is wrong? Its what I
intended to say. Oh, I see what you mean - fair enough. I suppose "the
array parameter" would have been better. Or?

,----
| >> is above. It is only to show that there are cases where arrays can be
| >> reassigned - in function calls where the compiler treats the parameter
| >> as a char *. The pointer is being rewritten : not the contents of what
| >> it originally pointed to.
`----
 
K

Keith Thompson

Richard said:
Keith Thompson said:
Richard said:
Schraalhans Keukenmeester <[email protected]>
writes:
According to www.c-faq.com (Q6.6)

--------
Q: If you can't assign to arrays, then how can

int f(char str[])
{
if(str[0] == '\0')
str = "none";
...
}

work?

A: In this code, str is a function parameter, so its declaration is
rewritten by the compiler as described in question 6.4. In other words,
str is a pointer (of type char *), and it is legal to assign to it.

----------

I see the logic why a value can be assigned to str in the function, but
would there be any point in doing so ? Am I wrong when I think the
passed array never gets the assigned value when the function returns?

No you are not wrong. You are misunderstanding the reason its done as it
is above. It is only to show that there are cases where arrays can be
reassigned - in function calls where the compiler treats the parameter
as a char *. The pointer is being rewritten : not the contents of what
it originally pointed to.
[...]

This is not a case where an array can be reassigned. It's a case
where something whose declaration *looks like* an array declaration
can be reassigned. str is a pointer, not an array.

Isn't that what I said? Maybe my terminology is wrong? Its what I
intended to say. Oh, I see what you mean - fair enough. I suppose "the
array parameter" would have been better. Or?

Not really, IMHO.

A point of terminology: the argument is the expression that appears in
the call, the parameter is the object declared in the function
declaration. (I don't mean to imply that you don't know this just
making sure everyone's talking about the same thing.)

Given the above function and a call like:

char arg[] = "hello";
...
str(arg);

there is neither an array argument (the expression "arg" is implicitly
converted to the address of its first element before the call, for
reasons that have nothing to do with the fact that it's a function
argument) nor an array parameter (in the prototype, "char str[]" isn't
just converted to a pointer it *means* "char *str"). In the body
of f(), the assignment
str = "none";
is simply a pointer assignment.

You're quite correct that

| The pointer is being rewritten : not the contents of what it
| originally pointed to.

but incorrect when you say before that that

| It is only to show that there are cases where arrays can be
| reassigned.

The code merely bears a superficial resemblance to what an array
assignment might look like, if such a thing existed in C.
 
S

Schraalhans Keukenmeester

Keith said:
Richard said:
Keith Thompson said:
Schraalhans Keukenmeester <[email protected]>
writes:
According to www.c-faq.com (Q6.6)

--------
Q: If you can't assign to arrays, then how can

int f(char str[])
{
if(str[0] == '\0')
str = "none";
...
}

work?
[snap]

Given the above function and a call like:

char arg[] = "hello";
...
str(arg);

there is neither an array argument (the expression "arg" is implicitly
converted to the address of its first element before the call, for
reasons that have nothing to do with the fact that it's a function
argument) nor an array parameter (in the prototype, "char str[]" isn't
just converted to a pointer it *means* "char *str"). In the body
of f(), the assignment
str = "none";
is simply a pointer assignment.

You're quite correct that

| The pointer is being rewritten : not the contents of what it
| originally pointed to.

but incorrect when you say before that that

| It is only to show that there are cases where arrays can be
| reassigned.

The code merely bears a superficial resemblance to what an array
assignment might look like, if such a thing existed in C.

Thanks a lot guys for your clear & concise explanations. Glad to see I
was right and at least start to have a grasp of this. Took me quite a
while, but after many hours of studying, experimenting and especially
reading the info on the site http://publications.gbdirect.co.uk/c_book/
I can honestly say I learned a lot. (Very good explanations imho, much
better than many of the books & texts I had read thusfar. It's old, not
updated for recent standards but good reading for novices I think,
especially the pointers & arrays parts)

I will also have a look at the text mentioned by Richard.

Cheers!
Sh.
 

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,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top