char * pass-by-value

A

Andrej Prsa

Hi,

sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

Thanks,

Andrej
 
P

pemo

Andrej said:
Hi,

sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

Yes, it's perfectly legal, and yes, that's how strlen works.

--
===============================================================
In an attempt to reduce 'unwanted noise' on the 'signal' ...

Disclaimer:

Any comment/code I contribute might =NOT= be 100% portable, nor
semantically correct [read - 'not 100% pedantically correct'].
I don't care too much about that though, and I reckon it's the
same with most 'visitors' here. However, rest assured that any
'essential' (?) corrections WILL almost certainly appear v.soon
[read - 'to add noise as they see fit, *a pedant* will be along
shortly'].

WARNINGS: Always read the label. No beside-the-point minutiae
filter supplied. Keep away from children. Do not ignite.
===============================================================
 
S

serrand

Andrej said:
Hi,

sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

Thanks,

Andrej


void strip2 (char in[])
{
in[strlen(in)-1] = '\0';
return;
}

same as

void strip1 (char *in)
{
*(in+strlen(in)-1) = '\0';
return;
}


N.B.
char * s is not equivalent to char s[] as you can see with the following :

char string[32] = "litte string";
char *ptr = string;
sizeof (string) ==> 32
sizeof (ptr) ==> 4 /* (on a machine with 4 byte pointers) */


N.B.
in+strlen(in)-1 is not very nice because of the substract ...
it's not very meaningfull to substract with pointers ...
in this case it's like (in + (strlen(in)-1))

xavier
 
C

Chris Dollin

Andrej said:
Hi,

sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

The string `in` had better have at least one character in it, or `in`
must point one (or more) character(s) into legal storage. Because
strlen(in) == 0 would mean you had `in[-1]=0`.

BOOM today - if you're lucky. Otherwise, BOOM tomorrow.
 
N

Nick Keighley

pemo said:
Andrej Prsa wrote:
sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

Yes, it's perfectly legal, and yes, that's how strlen works.

===============================================================
In an attempt to reduce 'unwanted noise' on the 'signal' ...

Disclaimer:

Any comment/code I contribute might =NOT= be 100% portable, nor
semantically correct [read - 'not 100% pedantically correct'].
I don't care too much about that though, and I reckon it's the
same with most 'visitors' here. However, rest assured that any
'essential' (?) corrections WILL almost certainly appear v.soon
[read - 'to add noise as they see fit, *a pedant* will be along
shortly'].

WARNINGS: Always read the label. No beside-the-point minutiae
filter supplied. Keep away from children. Do not ignite.
===============================================================

how does a 16 line sig added to a one line comment "reduce noise"?
 
P

Pedro Graca

Andrej said:
I am wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I am a newbie too, just want to point out somethings that could go wrong
with your function:

/* untested newbie code */
char *test;

test = NULL;
strip(test); /* BANG */

test = "";
strip(test); /* BANG */

test = "immutable string";
strip(test); /* BANG */

test = malloc(10);
if (test != NULL) {
strcpy(test, "");
strip(test); /* BANG */
}
I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

Yes, but maybe you should test for the various ways the function could
fail:

/* more newbie code */
void strip (char *in)
{
if (!in) return;
if (!*in) return;
in[strlen(in)-1] = '\0';
return;
}


I think there's something else about the function name:
isn't it reserved because it starts with "str" and continues with a
lowercase letter?
 
N

Nick Keighley

serrand said:
Andrej Prsa wrote:
sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

void strip2 (char in[])
{
in[strlen(in)-1] = '\0';
return;
}

same as

void strip1 (char *in)
{
*(in+strlen(in)-1) = '\0';
return;
}

so what? How does the help the OP? His original code is clearer.

N.B.
char * s is not equivalent to char s[] as you can see with the following :

char string[32] = "litte string";
char *ptr = string;
sizeof (string) ==> 32
sizeof (ptr) ==> 4 /* (on a machine with 4 byte pointers) */

N.B.
in+strlen(in)-1 is not very nice because of the substract ...
it's not very meaningfull to substract with pointers ...

since when? This has been perfectly well defined in C since K&R
in this case it's like (in + (strlen(in)-1))

I don't see what the extra parens buy you.
 
A

Andrej Prsa

Hi,

Thank you all very much for your very informative answers! :)

Best wishes,

Andrej
 
A

Arndt Jonasson

Andrej Prsa said:
sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

The function assumes that 'in' points to a string containing at least
one character. If you know that it always does, and it doesn't matter
what that last character is (I guess it's '\n' you're after), the
function seems fine to me, so it's legal and even arguably correct.
I would give it a more descriptive name, though.

If I wrote a function to strip newlines, I would check for the
existence of the newline at the end and let the string be unchanged if
there was no newline there.

The explicit "return" is not needed - the function ends there anyway.
 
V

Vladimir S. Oka

Pedro Graca wrote:

I think there's something else about the function name:
isn't it reserved because it starts with "str" and continues with a
lowercase letter?

Yes, there is. Standard states that all function names (identifiers)
starting with `str` and having a lowercase letter as the fourth
character are reserved for future use by the standard library.

So:

strip() -- bad idea
strMyWord() -- OK
str_ip() -- OK
str2rts( ) -- OK

Cheers

Vladimir
 
A

Arndt Jonasson

Pedro Graca said:
Andrej said:
I am wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I am a newbie too, just want to point out somethings that could go wrong
with your function:
test = "immutable string";
strip(test); /* BANG */

This one can often be made to give rise to a warning by the compiler.
With gcc, use -Wwrite-strings, and then interpret the text appropriately:

% gcc -Wwrite-strings strw.c
strw.c: In function `main':
strw.c:9: warning: initialization discards qualifiers from pointer target type

(If you want to make the string constant actually writable, the compiler
may provide an option for that too, but then it's not portable C.)
 
K

Kenneth Brody

Andrej said:
Hi,

sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

Yes, it's legal code, with the following caveats:

If the string passed is read-only, the above won't work. (I don't
recall if it's UB or "implementation defined".)

char *pt = "This string may be read-only";
...
strip(pt);

(I don't think there's anything you can do about that, however, beyond
documenting "don't do that".)

Second, you don't handle the case of a zero-length string being passed.

char str[] = "";
...
strip(str);

Finally, you don't handle a NULL parameter.

strip(NULL);

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
C

CBFalconer

Nick said:
pemo wrote:
.... snip ...
Yes, it's perfectly legal, and yes, that's how strlen works.

===============================================================
In an attempt to reduce 'unwanted noise' on the 'signal' ...

Disclaimer:

Any comment/code I contribute might =NOT= be 100% portable, nor
semantically correct [read - 'not 100% pedantically correct'].
I don't care too much about that though, and I reckon it's the
same with most 'visitors' here. However, rest assured that any
'essential' (?) corrections WILL almost certainly appear v.soon
[read - 'to add noise as they see fit, *a pedant* will be along
shortly'].

WARNINGS: Always read the label. No beside-the-point minutiae
filter supplied. Keep away from children. Do not ignite.
===============================================================

how does a 16 line sig added to a one line comment "reduce noise"?

Especially when it doesn't even have a proper sig marker.

--
"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/>
 
R

Richard Bos

CBFalconer said:
Especially when it doesn't even have a proper sig marker.

It did before Nick quoted it. That's about the only good thing about it.

Richard
 
K

Keith Thompson

Kenneth Brody said:
Andrej said:
sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?

Yes, it's legal code, with the following caveats:

If the string passed is read-only, the above won't work. (I don't
recall if it's UB or "implementation defined".)

char *pt = "This string may be read-only";
...
strip(pt);

(I don't think there's anything you can do about that, however, beyond
documenting "don't do that".)

I think that's the key to the whole thing. We can discuss what the
function will do (or how it will fail) given various arguments, but
what it really needs is documentation, a specification of what it's
*supposed* to do.
Second, you don't handle the case of a zero-length string being passed.

char str[] = "";
...
strip(str);

That's acceptable if the specification says not to pass it a
zero-length string -- but it would probably be better for the function
to do nothing in that case.
Finally, you don't handle a NULL parameter.

strip(NULL);

It's common for string functions to invoke undefined behavior if
called with a null pointer (see <string.h>), so that's not much of a
problem -- but again, it should be documented.

As others have mentioned the name "strip" is reserved. This is a bit
off-topic, but Perl has a built-in function "chop" that deletes the
last character of a string, and another built-in function "chomp" that
deletes the last character only if it's a newline; if I wanted to
write an equivalent C function, I'd probably use the same name.
 
J

Joe Wright

pemo said:
Andrej said:
Hi,

sorry for the newbie question; after reading the FAQ, I am still left
wondering if this is legal:

void strip (char *in)
{
in[strlen(in)-1] = '\0';
return;
}

I figure it is, because the memory location of the variable 'in' is
passed properly and I guess that the strlen() function seeks the '\0'
character to obtain its value. Is this true?


Yes, it's perfectly legal, and yes, that's how strlen works.

char in[] = "hello";
012345 Indexes into the string. in[5] is the '\0'.
strlen(n) is 5.
in[5-1] = '\0'; Will overwrite 'o' resulting in "hell".
 

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

Similar Threads

pass by address 42
pass by value 10
Filter table rows based on multiple checkboxes value 2
Pass variable by reference 6
pass string by value 4
pass by value question 4
pass temporary object by value 1
pass by value 7

Members online

Forum statistics

Threads
474,173
Messages
2,570,939
Members
47,484
Latest member
JackRichard

Latest Threads

Top