pass by reference

S

squid

I have a small program that passes a pointer to a function, the
function uses malloc to allocate some memory for it. When I return
the pointer in the function return value I can use it in the calling
function. But I am unable to use the pointer I passes as a
parameter. I am using Visual Studio C++ Express Edition. The program
compiles and runs.

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


char * getbuff(char *);


void main(void)
{
char *a, *b;
a = 0, b = 0;
b = getbuff(a);

return;
}


char * getbuff(char* p)
{
char * buff;
buff = (char *) malloc(sizeof(char) * 8);
p = buff;
return buff;
}
 
K

Keith Thompson

squid said:
I have a small program that passes a pointer to a function, the
function uses malloc to allocate some memory for it. When I return
the pointer in the function return value I can use it in the calling
function. But I am unable to use the pointer I passes as a
parameter. I am using Visual Studio C++ Express Edition. The program
compiles and runs.

What exactly do you mean when you say you're "unable to use" the
pointer? What results did you expect, what results did you get, and
how do they differ?
#include <stdio.h>
#include <stdlib.h>


char * getbuff(char *);


void main(void)

int main(void)
{
char *a, *b;
a = 0, b = 0;
b = getbuff(a);

return;

return 0;
}


char * getbuff(char* p)
{
char * buff;
buff = (char *) malloc(sizeof(char) * 8);

buff = malloc(8);
if (buff == NULL) {
/* error handling code */
}
p = buff;

p, like any parameter, is local to the function. Modifying it inside
the function doesn't do any good, unless you use the modified value
inside the function.

If you want a function to modify an object, you have to pass a pointer
to the object. It's the same if the object happens to be a pointer;
if you want your function to modify a pointer object, you have to pass
a pointer to the pointer (a char** in this case).
 
M

Mug

Greetings,







char *getbuffer(char **p)
{
   char *buff;

   buff = malloc(8);
   *p = buff;
   return buff;

}

casting malloc is frowned upon, sizeof(char) is 1 by definition, so
should be excluded.

There's no reason to initialize either a or b.

hello

buff = (char *) malloc(sizeof(char) * 8);

cast is neccessary since he compiled on a c++ compiler
if i do your way it will give me :

zsh 1430 % g++ malloc.c
malloc.c: In function ‘char* getbuffer(char**)’:
malloc.c:6: error: invalid conversion from ‘void*’ to ‘char*’

and moreover i think it's a good habitude write like:

buff = (char *) malloc(sizeof(char) * 8);
it make code clearer.

Mug
 
B

bartc

Richard Heathfield said:
Mug said:



If he's using a C++ compiler, he would get better answers in
comp.lang.c++ - and almost certainly the best answer he'll get will
not involve malloc at all.

He was refered here from comp.lang.c++, because his code used only the C
subset.
 
K

Keith Thompson

bartc said:
He was refered here from comp.lang.c++, because his code used only the
C subset.

He should decide which language he wants to use. That's not a
criticism of the OP, but he may have been given some poor advice.

If he's just using the "C subset" of C++ (more properly the
intersection of the two languages), he might as well use a C
compiler.

It's possible he has a legitimate reason to write code that's valid
C and C++ with the same meaning in both, but that's rare.
 
D

Default User

bartc said:
He was refered here from comp.lang.c++, because his code used only
the C subset.

More than that, he posted that he was working in C.




Brian
 
K

Keith Thompson

squid said:
I have a small program that passes a pointer to a function, the
function uses malloc to allocate some memory for it. When I return
the pointer in the function return value I can use it in the calling
function. But I am unable to use the pointer I passes as a
parameter. I am using Visual Studio C++ Express Edition. The program
compiles and runs.

What exactly do you mean when you say you're "unable to use" the
pointer? What results did you expect, what results did you get, and
how do they differ?
#include <stdio.h>
#include <stdlib.h>


char * getbuff(char *);


void main(void)

int main(void)
{
char *a, *b;
a = 0, b = 0;
b = getbuff(a);

return;

return 0;
}


char * getbuff(char* p)
{
char * buff;
buff = (char *) malloc(sizeof(char) * 8);

buff = malloc(8);
if (buff == NULL) {
/* error handling code */
}
p = buff;

p, like any parameter, is local to the function. Modifying it inside
the function doesn't do any good, unless you use the modified value
inside the function.

If you want a function to modify an object, you have to pass a pointer
to the object. It's the same if the object happens to be a pointer;
if you want your function to modify a pointer object, you have to pass
a pointer to the pointer (a char** in this case).
 
B

Barry Schwarz

snip

buff = (char *) malloc(sizeof(char) * 8);

cast is neccessary since he compiled on a c++ compiler
if i do your way it will give me :

He compiled on a product with C++ in its name. The product contains
(or is capable of functioning as) as C compiler.
zsh 1430 % g++ malloc.c
malloc.c: In function ‘char* getbuffer(char**)’:
malloc.c:6: error: invalid conversion from ‘void*’ to ‘char*’

and moreover i think it's a good habitude write like:

buff = (char *) malloc(sizeof(char) * 8);
it make code clearer.

If you think so, fine. I find superfluous casts clutter the code,
making it harder to read and maintain. Under the appropriate
conditions, it also allows the compiler to suppress what would
otherwise be a mandatory diagnostic thereby failing to alert you to
undefined behavior.
 
B

Barry Schwarz

Greetings,

Since p ceases to exist at the end of this function, this serves no
purpose.

If your function does not use one of its parameters, there is no need
for that parameter to exist. This will eliminate the need to pass
that parameter and also the need to assign it a value before
attempting to pass it.
 
N

Nick Keighley

that should be
int main (void)

void main is not standard

char *getbuffer(char **p)
{
   char *buff;
   buff = malloc(8);
   *p = buff;
   return buff;
}
casting malloc is frowned upon, sizeof(char) is 1 by definition, so
should be excluded.

don't quote sigs (the bit after "-- ")

buff = (char *) malloc(sizeof(char) * 8);

cast is neccessary since he compiled on a c++ compiler

How do you know? Visual Studio C++ Express Edition can be invoked
as a C compiler (despite the name it's quite a decent compiler).
How do you know he didn't do that?
if i do your way it will give me :

zsh 1430 % g++ malloc.c
malloc.c: In function ‘char* getbuffer(char**)’:
malloc.c:6: error: invalid conversion from ‘void*’ to ‘char*’

that's because you used a C++ compiler on C code.
Don't do that.
and moreover i think it's a good habitude write like:

buff = (char *) malloc(sizeof(char) * 8);
it make code clearer.

this is a matter of opinion. Most of the regular posters to this
news group (but not all) disagree with you.

A common idiom is

buff = malloc (sizeof(*buff) * 8);

which will continue to work correctly even if the type
of buff is changed (though I think it's a little too clever).
 
B

bartc

Barry Schwarz said:
Since p ceases to exist at the end of this function, this serves no
purpose.

If your function does not use one of its parameters, there is no need
for that parameter to exist. This will eliminate the need to pass
that parameter and also the need to assign it a value before
attempting to pass it.

There might be good reasons for unused parameters. For example, if the
function is one of a family of functions with the same interface, or a
function pointer is dereferenced where all the functions it can point to
have to conform.

Or there might be a piece of code not yet written for the parameter...
 
A

arnuld

I, on the other hand, don't think it's quite clever *enough*.

buff = malloc(sizeof *buff * 8);

is cleverer, because it more accurately reflects the nature of the
sizeof operator. Better still:


That gave me a little electric-shock at first when I saw it :)



buff = malloc(sizeof *buff * INIT_BUFF_SIZE);
...SNIP..
where init_buff_size is determined at run-time - although the
difference between the two is really a design decision, and runtime
decision-making is not always appropriate.

I think I still need to learn a lot from you.
 
B

Beej Jorgensen

Eric Sosman said:
buff = malloc(8 * sizeof * buff);

Ha!

On the parens note, I thought for a while that return required parens
around its expression just because my first C instructor always put them
there. (I don't know why.) Same with sizeof expression.

-Beej
 
L

luserXtrog

Richard said:
I, on the other hand, don't think it's quite clever *enough*.
buff = malloc(sizeof *buff * 8);
is cleverer, because it more accurately reflects the nature of the
sizeof operator. [...]

     Wimp.

        buff = malloc(8 * sizeof * buff);

;-)

For this construct, still more clever (IMNSHO) is to recognize
that '*' is not allowed in an identifier. It therefore serves
to delimit any adjacent identifiers, rendering all those spaces
superfluous.

buff = malloc(8*sizeof*buff);

;{>
 
B

Barry Schwarz

Richard said:
I, on the other hand, don't think it's quite clever *enough*.
buff = malloc(sizeof *buff * 8);
is cleverer, because it more accurately reflects the nature of the
sizeof operator. [...]

     Wimp.

        buff = malloc(8 * sizeof * buff);

;-)

For this construct, still more clever (IMNSHO) is to recognize
that '*' is not allowed in an identifier. It therefore serves
to delimit any adjacent identifiers, rendering all those spaces
superfluous.

buff = malloc(8*sizeof*buff);

So why did you leave spaces around the assignment operator?
 
L

luserXtrog

Richard Heathfield wrote:
I, on the other hand, don't think it's quite clever *enough*.
buff = malloc(sizeof *buff * 8);
is cleverer, because it more accurately reflects the nature of the
sizeof operator. [...]
     Wimp.
        buff = malloc(8 * sizeof * buff);
;-)
For this construct, still more clever (IMNSHO) is to recognize
that '*' is not allowed in an identifier. It therefore serves
to delimit any adjacent identifiers, rendering all those spaces
superfluous.
   buff = malloc(8*sizeof*buff);

So why did you leave spaces around the assignment operator?

I assumed (perhaps wrongly) that everyone already knew that those
spaces were unnecessary. Removing them would have distracted from
the specific detail I intended to point out. And my preference is
to have space around the = .

But why did you remove my moustaccio'd emoticon?
 

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,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top