By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,315 Members | 1,736 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,315 IT Pros & Developers. It's quick & easy.

simple malloc() problem

P: n/a
Can someone explain to a C newbie why this doesn't work as I expect it
to work? (expectations clearly outlined in the printf statement in
main routine)

OS: Linux 2.4.26
GCC: 2.95.4

void modify_pointer(char *);

int main(int argc, char *argv[]) {
char *ptr_to_string;
modify_pointer(ptr_to_string);
printf("but why doesn't this say hello? %s\n", ptr_to_string);
}

void modify_pointer(char *the_ptr) {
the_ptr = (char *) malloc(strlen("hello"));
strcpy(the_ptr, "hello");
printf("this says hello: %s\n", the_ptr);
}

--
output:

this says hello: hello
but why doesn't this say hello? p�

---
Nov 14 '05 #1
Share this Question
Share on Google+
33 Replies


P: n/a

"hermit_crab67" <he***********@yahoo.com> wrote in message news:52**************************@posting.google.c om...
Can someone explain to a C newbie why this doesn't work as I expect it
to work? (expectations clearly outlined in the printf statement in
main routine)

The problem isn't with the malloc (except the memory leakage here).
ptr_to_string has been passed by value, so the assigment

the_ptr = (char *) malloc(strlen("hello")); /* don't cast */

is local to the modify_pointer(). Do as follows:

OS: Linux 2.4.26
GCC: 2.95.4

void modify_pointer(char *);
void modify_pointer(char **);
int main(int argc, char *argv[]) {
char *ptr_to_string;
modify_pointer(ptr_to_string);
modify_pointer(&ptr_to_string);
printf("but why doesn't this say hello? %s\n", ptr_to_string);
}

void modify_pointer(char *the_ptr) {
the_ptr = (char *) malloc(strlen("hello"));
strcpy(the_ptr, "hello");
printf("this says hello: %s\n", the_ptr);
}


void modify_pointer(char **the_ptr) {
*the_ptr = malloc(sizeof("hello"));
strcpy(*the_ptr, "hello");
printf("this says hello: %s\n", *the_ptr);
}

This might be of some help:

In C, the only true method of parameter passing is known as "call by value".
The following example demonstrates the last statement:

#include <stdlib.h>

void
raisin ( float x ) { /* process x here */ }

void
grape ( float *xp ) { /* process xp here */ }

int
main ( void )
{
float f;
float *fp = &f;

/* ... */
raisin ( f );
grape ( fp );
return EXIT_SUCCESS;
}

When the declaration of an argument (f and fp) matches with the declaration
of the corresponding parameter (x and xp), then the argument has been passed by
value. And, when an argument is passed by value, any modification the called-
function makes to the parameter does not reflect in the calling-function. So,
any modification to xp does not reflect in fp, however, any modification to *xp
reflects in f.

--
Vijay Kumar R Zanvar
Pointers and Arrays - http://www.geocities.com/vijoeyz/art...dex.html#seq21
Nov 14 '05 #2

P: n/a
In 'comp.lang.c', he***********@yahoo.com (hermit_crab67) wrote:
Can someone explain to a C newbie why this doesn't work as I expect it
to work? (expectations clearly outlined in the printf statement in
main routine)

OS: Linux 2.4.26
GCC: 2.95.4

void modify_pointer(char *);
Starts badly. If you want to modify an object, you must pass the address of
it. Remember, in C, only the values are passed.

void modify_pointer(char **pp);

Your problem is covered by the FAQ:

http://www.eskimo.com/~scs/C-faq/q4.8.html
int main(int argc, char *argv[]) {
char *ptr_to_string;
This pointer is uninitialized.
modify_pointer(ptr_to_string);
Passing an uninitialized value to a function invokes an undefined behaviour.
Anything can happen. A decent and well-configured compiler should have warned
you about that.

Because you are using gcc (note: gcc is not GCC), I suggest you add this to
your command line:

-W -Wall -O2

and the following in addition if you want to comply to the C standard:

-ansi -pedantic
printf("but why doesn't this say hello? %s\n", ptr_to_string);
Be sure that <stdio.h> is included. printf() needs a prototype. It's
mandatory.
}

void modify_pointer(char *the_ptr) {
the_ptr = (char *) malloc(strlen("hello"));
Modifiying the value of a parameter is often the indication of a bad design.

No need for the cast. Be sure that you have included <stdlib.h>. malloc() can
fail. You must test the returned value against NULL.

strlen() wants <string.h>. It returns the length of the string, not it's
size. You're off by one.

char * the_ptr = malloc(strlen("hello") + 1);

or, in this special case involving a string literal:

char * the_ptr = malloc(sizeof "hello");
strcpy(the_ptr, "hello");
But it is recommended to avoid such repetitions.
- Not all compilers are smart enough to merge similar string literals, hence
a waste of space.
- It makes maintenance a hell

I recommend an initialized array of const char:

char const s[] = "hello";
char * the_ptr = malloc(strlen(S) + 1);

if (the_ptr != NULL)
{
strcpy(the_ptr, S);
<...>
}
printf("this says hello: %s\n", the_ptr);
}


Not to mention that the value of 'the_ptr' must now be returned via the new
char ** pp parameter (after having checked that pp is not NULL, of course).

if (pp != NULL)
{
*pp = the_ptr;
}

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=c99
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
Nov 14 '05 #3

P: n/a
Emmanuel Delahaye wrote:
Modifiying the value of a parameter is often the indication of a bad design.


I'm interested in your thoughts behind this statement.

Case

Nov 14 '05 #4

P: n/a
In 'comp.lang.c', Case <no@no.no> wrote:
Modifiying the value of a parameter is often the indication of a bad
design.


I'm interested in your thoughts behind this statement.


The code given by the original poster is a perfect illustration of this
statement.

Apart for micro-optimisation purpose, there is not good reasons for a
parameter to have its value changed. This is the reason why, at a first
glance, I recommend to define the parameters with const. If it clashes
somewhere, it means that it's time to think harder about the design.

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=c99
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
Nov 14 '05 #5

P: n/a
Case wrote:
Emmanuel Delahaye wrote:
Modifiying the value of a parameter is often the indication of
a bad design.


I'm interested in your thoughts behind this statement.


This is a religious issue, on which E.D. and I disagree. I treat
parameters as externally initialized local variables (which they
are). If a function is so long that I can't easily spot the need
for the original value, then there is a design problem and the
function needs to be broken up into smaller and simpler functions.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #6

P: n/a
In <Xn**************************@212.27.42.74> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Case <no@no.no> wrote:
Modifiying the value of a parameter is often the indication of a bad
design.
I'm interested in your thoughts behind this statement.


Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.
The code given by the original poster is a perfect illustration of this
statement.


And the following code is a perfect rebuttal of the same statement:

#include <stdio.h>

int main(int argc, char **argv)
{
while (argc-- > 0) puts(*argv++);
return 0;
}

At the end of the loop, the initial values of argc and argv are
entirely irrelevant, so there is no *good* (i.e. non-religious) reason
for preserving them.

And although this is a trivial example, it is typical for code parsing
its command line arguments. See also the example at page 117 in K&R2.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #7

P: n/a
Dan Pop <Da*****@cern.ch> scribbled the following:
In <Xn**************************@212.27.42.74> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Case <no@no.no> wrote:
Modifiying the value of a parameter is often the indication of a bad
design.

I'm interested in your thoughts behind this statement.
Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.


As it stands, I happen to agree with him. Emphasis on "often the
indication of" bit. There are legitimate causes for modifying the value
of a parameter but usually it's a sign of the programmer not
understanding how C's parameter passing works.

--
/-- Joona Palaste (pa*****@cc.helsinki.fi) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"There's no business like slow business."
- Tailgunner
Nov 14 '05 #8

P: n/a
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.
I was naively thinking that Usenet was not the place for nominative attacks.
Sounds that I was wrong. My statements belong to my coding guidelines that
result from a rather long experience in C-programming. You may gently agree
or not, byt why being so harsh ?
The code given by the original poster is a perfect illustration of this
statement.


And the following code is a perfect rebuttal of the same statement:

#include <stdio.h>

int main(int argc, char **argv)
{
while (argc-- > 0) puts(*argv++);
return 0;
}

At the end of the loop, the initial values of argc and argv are
entirely irrelevant, so there is no *good* (i.e. non-religious) reason
for preserving them.


What a strange example. What if I now want to access to the arguments ? Or to
check the number of arguments?

Your example illustrates exactly what I try to fight against : the
destruction of the initial value of a parameter.
And although this is a trivial example, it is typical for code parsing
its command line arguments. See also the example at page 117 in K&R2.


I think that I'm not the one that consider the K&R2 a Sacred Book. Who is the
one with a religious attitude ?

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=c99
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
Nov 14 '05 #9

P: n/a
Dan Pop wrote:
In <Xn**************************@212.27.42.74> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Case <no@no.no> wrote:
Modifiying the value of a parameter is often the indication of a bad
design.

I'm interested in your thoughts behind this statement.


Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.
The code given by the original poster is a perfect illustration of this
statement.


And the following code is a perfect rebuttal of the same statement:

#include <stdio.h>

int main(int argc, char **argv)
{
while (argc-- > 0) puts(*argv++);
return 0;
}

At the end of the loop, the initial values of argc and argv are
entirely irrelevant, so there is no *good* (i.e. non-religious) reason
for preserving them.


Appreciated.

- Dario
Nov 14 '05 #10

P: n/a
hermit_crab67 wrote:
Can someone explain to a C newbie why this doesn't work as I expect it
to work? (expectations clearly outlined in the printf statement in
main routine)
The real questions are
1) Why are you ignoring the diagnostics from the compiler
2) If you don't see any diagnostics, why do you have them turned off?
3) Why don't you check the FAQ before posting, as civilized human beings do?

A fixed version of your code follows the reproduction of your original code.

OS: Linux 2.4.26
GCC: 2.95.4
If the particular operating system or compiler were relevant to your
question (they aren't), then your question would be a heavy favorite to
be off-topic here and to belong in a Linux or GCC newsgroup or mailing list.

void modify_pointer(char *);

int main(int argc, char *argv[]) {
char *ptr_to_string;
modify_pointer(ptr_to_string);
printf("but why doesn't this say hello? %s\n", ptr_to_string);
}

void modify_pointer(char *the_ptr) {
the_ptr = (char *) malloc(strlen("hello"));
strcpy(the_ptr, "hello");
printf("this says hello: %s\n", the_ptr);
}

#include <stdio.h> /* mha: added, variadic printf _must_
have a prototype in scope */
#include <stdlib.h> /* mha: added */
#include <string.h> /* mha: added */

void modify_pointer(char **); /* mha: added level of indirection */

int main(void)
{
char *ptr_to_string;
modify_pointer(&ptr_to_string); /* mha: added address-of operator */
printf("but why doesn't this say hello? %s\n", ptr_to_string);
free(ptr_to_string); /* mha: added */
return 0; /* mha: added */
}

void modify_pointer(char **the_ptr)
{ /* mha: added level of indirection */
#if 0
the_ptr = (char *) malloc(strlen("hello"));
#endif
/* mha: the above fixed below */
if (!(*the_ptr = malloc(1 + strlen("hello")))) {
fprintf(stderr, "Malloc failed, quitting...\n");
exit(EXIT_FAILURE);
}
strcpy(*the_ptr, "hello"); /* mha: added level of indirection */
printf("this says hello: %s\n", *the_ptr); /* mha: added level of
indirection */
}
Nov 14 '05 #11

P: n/a
In <cb**********@oravannahka.helsinki.fi> Joona I Palaste <pa*****@cc.helsinki.fi> writes:
Dan Pop <Da*****@cern.ch> scribbled the following:
In <Xn**************************@212.27.42.74> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Case <no@no.no> wrote:
> Modifiying the value of a parameter is often the indication of a bad
> design.

I'm interested in your thoughts behind this statement.

Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.


As it stands, I happen to agree with him. Emphasis on "often the
indication of" bit. There are legitimate causes for modifying the value
of a parameter but usually it's a sign of the programmer not
understanding how C's parameter passing works.


Nonsense! It is only very green newbies that *might* expect changes made
to a function parameter to be visible from the caller. Not even them,
with a good instructor/book.

Once you understand that parameters are locals initialised by the caller,
you have no reason not to change their values, and if you have such a
reason, declare them as const.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #12

P: n/a
On 21 Jun 2004 09:19:07 GMT, in comp.lang.c , Emmanuel Delahaye
<em**********@noos.fr> wrote:
In 'comp.lang.c', Case <no@no.no> wrote:
Modifiying the value of a parameter is often the indication of a bad
design.
I'm interested in your thoughts behind this statement.


This is the reason why, at a first
glance, I recommend to define the parameters with const.


well.... I disagree. Modifying a pointer parameter is pretty common
practice I think.
If it clashes somewhere, it means that it's time to think harder about the design.


And if its not a pointer parameter, then modifying it is no different to
modifying any other local variable.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 14 '05 #13

P: n/a
On 21 Jun 2004 16:18:20 GMT, in comp.lang.c , Emmanuel Delahaye
<em**********@noos.fr> wrote:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.


I was naively thinking that Usenet was not the place for nominative attacks.
Sounds that I was wrong. My statements belong to my coding guidelines that
result from a rather long experience in C-programming. You may gently agree
or not, byt why being so harsh ?


its just dan's way of interacting with humans. Just ignore it.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 14 '05 #14

P: n/a
In <Xn***************************@212.27.42.71> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.
I was naively thinking that Usenet was not the place for nominative attacks.


I can see no attack, merely an accurate statement of fact.
Sounds that I was wrong. My statements belong to my coding guidelines that
result from a rather long experience in C-programming. You may gently agree
or not, byt why being so harsh ?
Because, *far too often*, you present your religion as a matter of fact,
which it isn't!
The code given by the original poster is a perfect illustration of this
statement.


And the following code is a perfect rebuttal of the same statement:

#include <stdio.h>

int main(int argc, char **argv)
{
while (argc-- > 0) puts(*argv++);
return 0;
}

At the end of the loop, the initial values of argc and argv are
entirely irrelevant, so there is no *good* (i.e. non-religious) reason
for preserving them.


What a strange example. What if I now want to access to the arguments ? Or to
check the number of arguments?


Then, you code it differently. Note, however, that, since this is a
*complete* program, you don't want to do anything else than it is already
being done.
Your example illustrates exactly what I try to fight against : the
destruction of the initial value of a parameter.
Which is NOT any more sacred than the initial value of any of the
function's local variables. But you seem to have a difficulty
understanding that.
And although this is a trivial example, it is typical for code parsing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ its command line arguments. See also the example at page 117 in K&R2.

^^^^^^^^^^^^^^^^^^^^^^^^^^
I think that I'm not the one that consider the K&R2 a Sacred Book.
Neither am I, especially considering that this particular example has
some problems under standard C ;-) However, the more experienced I get,
the more reasons I have to appreciate this book.
Who is the one with a religious attitude ?


How do you parse "see also"? How do you parse the underlined text above?
Is there any connotation that this is the one and only right way of doing
it? Nope. It is a strong statement that things can be done this way and
there is nothing wrong with doing them this way, but there is no
implication that doing them differently would be actually wrong. Compare
that with your statement which says: "it is wrong to do things this way".

You're saying "it is wrong if, at the end of the function's execution,
the parameters don't have their initial values" while I am NOT saying
"it is wrong if, at the end of the function's execution, the parameters
still have their initial values". So, my position cannot be religious,
*by definition*. That is, assuming that we both have the same idea
about what "religion" means.

The right decision must be made on a case by case basis rather than
being a priori decided. No place here even for a "most often".
This is called "pragmatism" and it *is* my "religion" ;-)

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #15

P: n/a


Emmanuel Delahaye wrote:
void modify_pointer(char *);

Starts badly. If you want to modify an object, you must pass the address of
it. Remember, in C, only the values are passed.

void modify_pointer(char **pp);

.....snip...

char const s[] = "hello";
char * the_ptr = malloc(strlen(S) + 1);

if (the_ptr != NULL)
{
strcpy(the_ptr, S);
<...>
}


Not to mention that the value of 'the_ptr' must now be returned via the new
char ** pp parameter (after having checked that pp is not NULL, of course).

if (pp != NULL)
{
*pp = the_ptr;
}


This is rather poor advise. Why test for pp being a NULL value
after having attempted the dynamic allocation? If pp is NULL the malloc
and strcpy statements would be rattlebrain.

I would suggest the op modify the function prototype and definiton
to include a return value that can be tested for success/failure of the
modification and an extra parameter that would indicated the source
of the amendment.

char * modify_pointer(char **pp, const char *newstring);

The definition and useage:

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

char *modify_pointer(char **pp, const char *teststring)
{
char *tmp;

if(pp == NULL || teststring == NULL) return NULL;
if((tmp = realloc(*pp,strlen(teststring)+1)) == NULL)
return NULL;
strcpy(tmp,teststring);
return (*pp = tmp);
}

void myfree(char **s)
{
free(*s);
*s = NULL;
return;
}

int main(void)
{
char *s = NULL; /* Initial NULL value neccessary */

if(modify_pointer(&s,"Hello"))
printf("s points to string: \"%s\"\n",s);
else puts("pointer s is a null pointer");
puts("\nAttempting modify.....\n");
if(modify_pointer(&s,"Goodbye"))
printf("s points to string: \"%s\"\n",s);
else puts("pointer s is a null pointer");
myfree(&s);
return 0;
}
--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #16

P: n/a
On Mon, 21 Jun 2004, Joona I Palaste wrote:
Dan Pop <Da*****@cern.ch> scribbled the following:
In <Xn**************************@212.27.42.74> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Case <no@no.no> wrote:
> Modifiying the value of a parameter is often the indication of a bad
> design.

I'm interested in your thoughts behind this statement.
Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.


As it stands, I happen to agree with him. Emphasis on "often the
indication of" bit. There are legitimate causes for modifying the value
of a parameter but usually it's a sign of the programmer not
understanding how C's parameter passing works.


I didn't read the same thing from Emmanuel's posting. A bad DESIGN is not
a bad program. A programmer not understanding how parameters are passed in
C is not a bad design; that is just bad programming.

To say that by DESIGN I should not modify the input parameters to a
function is a matter of choice. If the program does what is intended and
the code is maintainable then it becomes a matter of opinion.

If Emmanuel meant that modifying the input parameters to a function is
usually the result of a programmer misunderstanding how parameters are
passed in C then I would agree. I see more programmers doing this because
they misunderstand parameter passing than because they just like to reuse
variables.

If anyone tells me that you must never modify the input parameters to a
function then I take that as their opinion.
--
/-- Joona Palaste (pa*****@cc.helsinki.fi) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"There's no business like slow business."
- Tailgunner


--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov
Nov 14 '05 #17

P: n/a
On Mon, 21 Jun 2004, Emmanuel Delahaye wrote:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.
I was naively thinking that Usenet was not the place for nominative attacks.
Sounds that I was wrong. My statements belong to my coding guidelines that
result from a rather long experience in C-programming. You may gently agree
or not, byt why being so harsh ?


Dan does this to everyone. He has done it to me. I don't take it
personally. I've actually learn to question things other people tell me as
fact. I've come to realize that many things I take as fact are just my
opinion.

If I was working for Dan and he wanted to modify input parameters, so be
it. If I'm working for you and you state, no modifying input parameters,
never will an input parameter be modified.

Why? Because it is such a trivial matter.
The code given by the original poster is a perfect illustration of this
statement.


And the following code is a perfect rebuttal of the same statement:

#include <stdio.h>

int main(int argc, char **argv)
{
while (argc-- > 0) puts(*argv++);
return 0;
}

At the end of the loop, the initial values of argc and argv are
entirely irrelevant, so there is no *good* (i.e. non-religious) reason
for preserving them.


What a strange example. What if I now want to access to the arguments ? Or to
check the number of arguments?


Do not modify the input parameters if you know you are going to need them
more than once. If you need to access them twice it would be foolish to
use them once in a way that modified them.

You might counter with, "what if you designed it such that you modified
the input parameters and later (version 2.0 perhaps) realized you needed
to access the parameters twice?" Simple, put a piece of code at the top of
the function that saves the input paramters into backup variables. Later
when you need to access the input parameters a second time, use the backup
variables. Puts you right back to where you would have been if you didn't
modify the input parameters in the first place.
Your example illustrates exactly what I try to fight against : the
destruction of the initial value of a parameter.
And although this is a trivial example, it is typical for code parsing
its command line arguments. See also the example at page 117 in K&R2.


I think that I'm not the one that consider the K&R2 a Sacred Book. Who is the
one with a religious attitude ?


I took his reference to K&R2, "here is a trivial example, if you want to
see a more complex example it is on page 117... I'm just too lazy to type
in the example myself."

Bottom line, Dan can be a little harsh at times but you have to look at
what he is saying rather than taking it personally by looking at how he is
saying it.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov
Nov 14 '05 #18

P: n/a
In article <Pi******************************@drj.pf>
Darrell Grainger <da*****@NOMORESPAMcs.utoronto.ca.com> writes:
Do not modify the input parameters if you know you are going to need them
more than once. If you need to access them twice it would be foolish to
use them once in a way that modified them.

You might counter with, "what if you designed it such that you modified
the input parameters and later (version 2.0 perhaps) realized you needed
to access the parameters twice?" Simple, put a piece of code at the top of
the function that saves the input paramters into backup variables. ...


Or, as I often do:

void fn(int iparm, char *sparm) { /* first version */
... code that modifies iparm and sparm ...
}

becomes:

void fn(int iparm0, char *sparm0) { /* second version */
int iparm = iparm0;
char *sparm = sparm0;
... code that *still* modifies iparm and sparm ...
}

The original values are now available under the new names iparm0
and sparm0 as needed. (I *might* even make those "const" at this
point, just for emphasis, but probably not. As a rule I try not
to modify x-sub-nought though -- this is sort of a C translation
of the mathematical notion of a sequence, where x-sub-0 is the
initial state and each x-sub-i is derived from the previous state.)

I also (perhaps inconsistently) tend to use this zero-suffix for
incoming pointer values that, for interface reasons, have type
"void *" instead of the desired type:

int xyz_interrupt(void *sc0) {
struct xyz_softc *sc = sc0;
...
return flag_indicating_whether_it_was_this_device_that_in terrupted;
}

In general I do not use "const" much at all. I think the two main
reasons I avoid peppering C code with this spice are because I have
been using C since before it existed, and because const does not
really work right in C. (See the earlier posting about "const int
arr[][SIZE]" as a parameter, which really means "const int
(*arr)[SIZE]", which cannot be used to point to the various rows
of a regular "int somearr[SOMEROWS][SIZE]" variable.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #19

P: n/a
Thanks all for the help.

I think I understand the issues at a conceptual level much better
after reading these posts. Basically if I understand it correctly,
the contents that the pointer points to can be modified by the local
function, and those changes will persist after the function loses
scope, but the *pointer itself* cannot be, and only a copy will be
modified -- and that copy will disappear once the function goes out of
scope. Since malloc() is modifying the pointer itself, those changes
are discarded once the method goes out of scope.

This can be corrected by passing in a pointer to a pointer, for one
more level of indirection, (as posted) or the pointer can be
initialized/malloc'd outside of the local function. (discovered via
trial/error)

Next time I will check the FAQ, and my Makefile now has those warning
flags. Posting etiquette tips duly noted.
Nov 14 '05 #20

P: n/a
Da*****@cern.ch (Dan Pop) writes:
In <Xn***************************@212.27.42.71> Emmanuel Delahaye
<em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
Like most such statements made by Emmanuel, it's a matter of pure
religion taken as fact.


I was naively thinking that Usenet was not the place for nominative
attacks.


I can see no attack, merely an accurate statement of fact.


No, Dan, it's your opinion.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #21

P: n/a
In <ln************@nuthaus.mib.org> Keith Thompson <ks***@mib.org> writes:
Da*****@cern.ch (Dan Pop) writes:
In <Xn***************************@212.27.42.71> Emmanuel Delahaye
<em**********@noos.fr> writes:
>In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
>
>> Like most such statements made by Emmanuel, it's a matter of pure
>> religion taken as fact.
>
>I was naively thinking that Usenet was not the place for nominative
>attacks.


I can see no attack, merely an accurate statement of fact.


No, Dan, it's your opinion.


Based on facts accumulated over a period of several years. Easily
verifiable with Google, if you have nothing better to do...

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #22

P: n/a
In <Pi******************************@drj.pf> da*****@NOMORESPAMcs.utoronto.ca.com (Darrell Grainger) writes:
If I was working for Dan and he wanted to modify input parameters, so be
it.


All I want from a programmer is to do whatever makes most sense under the
specific circumstances, rather than using a system of *inflexible* rules.

Come to think of it, my own inflexible rules are:

1. Identifiers must make as much sense as possible in as few characters
as possible.

2. Code must be indented (the style doesn't matter).

3. Dereferencing a function pointer must not look like an ordinary
function call.

4. Macros should be spelled in upper case (with the possible exception
of those having the same semantics as a function call).

5. typedef is not a typing saving device.

6. Reserve implicit comparisons against 0 for conceptual booleans.

7. If a function can fail, don't ignore checking its success, unless there
is a good reason for that.

8. Don't use any declaration more complex than the declaration of a
pointer to function or pointer to array. For anything more complex
than that, use typedefs.

With one exception (related to correctness) all of them are related to
writing readable C code (or what I consider readable C code).

Maintainable C code is, for me, at least, a matter of code design rather
than than code writing.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #23

P: n/a

"Dan Pop" <Da*****@cern.ch> wrote in message
news:cb**********@sunnews.cern.ch...
In <Pi******************************@drj.pf> da*****@NOMORESPAMcs.utoronto.ca.com (Darrell Grainger) writes:
If I was working for Dan and he wanted to modify input parameters, so be
it.


All I want from a programmer is to do whatever makes most sense under the
specific circumstances, rather than using a system of *inflexible* rules.

Come to think of it, my own inflexible rules are:

1. Identifiers must make as much sense as possible in as few characters
as possible.

2. Code must be indented (the style doesn't matter).

3. Dereferencing a function pointer must not look like an ordinary
function call.

4. Macros should be spelled in upper case (with the possible exception
of those having the same semantics as a function call).

5. typedef is not a typing saving device.

6. Reserve implicit comparisons against 0 for conceptual booleans.

7. If a function can fail, don't ignore checking its success, unless there
is a good reason for that.

8. Don't use any declaration more complex than the declaration of a
pointer to function or pointer to array. For anything more complex
than that, use typedefs.


Thank you, thank you, thank you.

I get so annoyed at those who fall back on:
"Anyone who knows C should be able to read this."

Although wrt #5 in the list. I have been guilty of using #define as a
typing
saving device. Of course, I justify by saying "it ensures consistent
usage".

Rufus

Nov 14 '05 #24

P: n/a
Dan Pop wrote:
2. Code must be indented (the style doesn't matter).

I'd add that the indentation style should be internally consistent.

Brian Rodenborn
Nov 14 '05 #25

P: n/a
Emmanuel Delahaye wrote:
Your problem is covered by the FAQ:

http://www.eskimo.com/~scs/C-faq/q4.8.html


I went to the faq and it looks like:

void f(ip)
int *fp;
{
static int dummy = 5;
ip = &dummy;
}

shouldn't the above read:

int *fp;

void f(ip) {

static int dummy = 5;
ip = &dummy;
}

If so, could you correct it?

Brian

P.S. The FAQ really does answer the question even
though the poster thought their problem
was malloc(), which had the wrong size_t --
cutting off '\0'.

Note: The only item I can find regarding casting
of malloc() is K&R2 pg. 142:

"In C, the proper method is to declare that
malloc return a pointer to void, then
explicitly coerce the pointer into the
desired type with cast."

Now, I couldn't find anything specific in
ISO C99, so I guess it's up to the programmer
to decide.
Nov 14 '05 #26

P: n/a
tweak <xb**********@cox.net> writes:
Emmanuel Delahaye wrote:
Your problem is covered by the FAQ:
http://www.eskimo.com/~scs/C-faq/q4.8.html
I went to the faq and it looks like:

void f(ip)
int *fp;
{
static int dummy = 5;
ip = &dummy;
}


Not quite. It actually looks like this:

void f(ip)
int *ip;
{
static int dummy = 5;
ip = &dummy;
}

There is no "fp".

The code fragment uses an old-style function declaration, which is
a bit odd. I'd prefer this:

void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
shouldn't the above read:

int *fp;

void f(ip) {

static int dummy = 5;
ip = &dummy;
}


Um, no.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #27

P: n/a
Keith Thompson wrote:
tweak <xb**********@cox.net> writes:
Emmanuel Delahaye wrote:

Your problem is covered by the FAQ:
http://www.eskimo.com/~scs/C-faq/q4.8.html


I went to the faq and it looks like:

void f(ip)
int *fp;
{
static int dummy = 5;
ip = &dummy;
}

Not quite. It actually looks like this:

void f(ip)
int *ip;
{
static int dummy = 5;
ip = &dummy;
}

There is no "fp".

The code fragment uses an old-style function declaration, which is
a bit odd. I'd prefer this:

void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}

shouldn't the above read:

int *fp;

void f(ip) {

static int dummy = 5;
ip = &dummy;
}

Um, no.

Thanks for correcting me. I've never seen the style before.

Yeah. It should be fp(int *ip).

Thanks,

Brian
Nov 14 '05 #28

P: n/a
Keith Thompson <ks***@mib.org> wrote:
tweak <xb**********@cox.net> writes:
Emmanuel Delahaye wrote:
> Your problem is covered by the FAQ:
> http://www.eskimo.com/~scs/C-faq/q4.8.html
I went to the faq and it looks like:

void f(ip)
int *fp;
{

[...]Not quite. It actually looks like this:

void f(ip)
int *ip;
{ [...]The code fragment uses an old-style function declaration, which is
a bit odd.


This is due to the fact that the HTML rendition of the FAQ is *not*
the most recent version. In the up-to-date text version the old-style
declaration is sensibly replaced by:

void f(int *ip)
{
[...]

I suggest to always use the text version of the FAQ.

Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #29

P: n/a
tweak wrote:
Note: The only item I can find regarding casting
of malloc() is K&R2 pg. 142:


Check the errata:
http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html

142(6.5, toward the end): The remark about casting the return value
of malloc ("the proper method is to declare ... then
explicitly coerce") needs to be rewritten. The example is correct
and works, but the advice is debatable in the context of the
1988-1989 ANSI/ISO standards. It's not necessary
(given that coercion of void * to ALMOSTANYTYPE * is automatic),
and possibly harmful if malloc, or a proxy for it,
fails to be declared as returning void *.
The explicit cast can cover up an unintended error.
On the other hand, pre-ANSI, the cast was necessary,
and it is in C++ also.

--
pete
Nov 14 '05 #30

P: n/a
On Tue, 22 Jun 2004, tweak wrote:
Emmanuel Delahaye wrote:
Your problem is covered by the FAQ:

http://www.eskimo.com/~scs/C-faq/q4.8.html
I went to the faq and it looks like:

void f(ip)
int *fp;
{
static int dummy = 5;
ip = &dummy;
}


Actually, it is:

void f(ip)
int *ip
{
static int dummy = 5;
ip = &dummy;
}

This is the old way of declaring a function. You list all the parameters
without their type in the () area. Then on lines between the first line
and the { you place the parameter types. The main function would be
written as:

int main(argc, argv)
int argc;
char **argv;
{
/* your code here */
return 0;
}

It is good to know this format for those times you need to maintain some
old code but you should not use this format anymore.
P.S. The FAQ really does answer the question even
though the poster thought their problem
was malloc(), which had the wrong size_t --
cutting off '\0'.
This would have been covered by:

http://www.eskimo.com/~scs/C-faq/q7.19.html
Note: The only item I can find regarding casting
of malloc() is K&R2 pg. 142:

"In C, the proper method is to declare that
malloc return a pointer to void, then
explicitly coerce the pointer into the
desired type with cast."

Now, I couldn't find anything specific in
ISO C99, so I guess it's up to the programmer
to decide.


The FAQ http://www.eskimo.com/~scs/C-faq/q7.6.html talks about the correct
thing to do but it does not explain why casting the result of malloc is a
bad thing. Also http://www.eskimo.com/~scs/C-faq/q7.7.html talks about the
history of why code had previously cast the result of malloc but again, it
does not talk about why it is now a bad thing.

I guess "Why is casting the result of malloc a bad thing?" would make for
a good FAQ.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov
Nov 14 '05 #31

P: n/a
"Darrell Grainger" <da*****@NOMORESPAMcs.utoronto.ca.com> wrote in message
news:Pi******************************@drj.pf...

I guess "Why is casting the result of malloc a bad thing?" would make for
a good FAQ.


This FAQ has been beaten to death in clc. Ben Pfaff has provided a VGA
(Very Good Answer) at http://benpfaff.org/writings/clc/malloc-cast.html.

--
Tim Hagan
Nov 14 '05 #32

P: n/a
pete wrote:
tweak wrote:

Note: The only item I can find regarding casting
of malloc() is K&R2 pg. 142:

Check the errata:
http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html

142(6.5, toward the end): The remark about casting the return value
of malloc ("the proper method is to declare ... then
explicitly coerce") needs to be rewritten. The example is correct
and works, but the advice is debatable in the context of the
1988-1989 ANSI/ISO standards. It's not necessary
(given that coercion of void * to ALMOSTANYTYPE * is automatic),
and possibly harmful if malloc, or a proxy for it,
fails to be declared as returning void *.
The explicit cast can cover up an unintended error.
On the other hand, pre-ANSI, the cast was necessary,
and it is in C++ also.

Thanks.

I didn't know there was a errata from the book available since
it's pretty old.

Thanks Again,

Brian

P.S. Sorry about messing up my understanding of the syntax.
Nov 14 '05 #33

P: n/a
On Wed, 23 Jun 2004, Tim Hagan wrote:
"Darrell Grainger" <da*****@NOMORESPAMcs.utoronto.ca.com> wrote in message
news:Pi******************************@drj.pf...

I guess "Why is casting the result of malloc a bad thing?" would make for
a good FAQ.
This FAQ has been beaten to death in clc. Ben Pfaff has provided a VGA
(Very Good Answer) at http://benpfaff.org/writings/clc/malloc-cast.html.


I'm suggesting that it should be added to the comp.lang.c official FAQ.
--
Tim Hagan


--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov
Nov 14 '05 #34

This discussion thread is closed

Replies have been disabled for this discussion.