pointer in front of a function ???

2

2005

1) What is the big deal about * in front of RandStr ? - I guess it
means pointer to function - but what are the benefits?
2) If I call the RandStr in main or another function, would
char str[6];
str = RandStr
work? Why not?

char *RandStr(void)
{
int i;
char RandStr[5];
for(i = 0; i <= 5; i++)
{
RandStr = rand() % 78;
}
return RandStr;
}
 
B

Ben Pfaff

2005 said:
1) What is the big deal about * in front of RandStr ? - I guess it
means pointer to function - but what are the benefits?

In "char *RandStr(void)", the "char *" means "pointer to
character". That is, the * binds to "char", not to RandStr().
2) If I call the RandStr in main or another function, would
char str[6];
str = RandStr
work? Why not?

No. This function returns a pointer, but "str" is an array. You
can't assign a pointer to an array. You can't assign anything to
an array (although you may be able to assign to an array's
elements).
 
A

Andrew Poelstra

1) What is the big deal about * in front of RandStr ? - I guess it
means pointer to function - but what are the benefits?

Nope - it means that instead of returning a char, you're
returning a pointer to char. A very different beast.
2) If I call the RandStr in main or another function, would
char str[6];
str = RandStr
work? Why not?

No, because you can't assign to arrays directly like that. There
was another thread about exactly this earlier today; see if you
can find it on groups.google.com or something.
char *RandStr(void)
{
int i;
char RandStr[5];

Here you use the same name for a char[5] as you do for the function.
this is legal and won't cause any trouble as long as you don't use
any recursion. But it's terrible style and will confuse people who
are reading the code.
for(i = 0; i <= 5; i++)
{
RandStr = rand() % 78;


This won't give you printable characters on any charset I've used.
(Well, /some/ will be printable. Maybe. Others will be print control
characters and beeps. Maybe.)

Consider using the RandStr() I gave you in the other thread.
}
return RandStr;
}

Yikes! You can't do this because RandStr[] was allocated locally
in your function - so when you return, RandStr[] dies. And you
return a pointer to it, which if used, will result in Undefined
Behavior.

If you allocated RandStr with malloc() (including <stdlib.h>!)
or passed it into the function, it would keep on living after
the function returns, and you'd be safe.

But remember to free() anything you get with malloc(), or you'll
have a memory leak on your hands.
 
2

2005

1) What is the big deal about * in front of RandStr ?  - I guess it
means pointer to function - but what are the benefits?

Nope - it means that instead of returning a char, you're
returning a pointer to char. A very different beast.
2) If I call the RandStr in main or another function, would
char str[6];
str = RandStr
work?  Why not?

No, because you can't assign to arrays directly like that. There
was another thread about exactly this earlier today; see if you
can find it on groups.google.com or something.
char *RandStr(void)
{
        int i;
        char RandStr[5];

Here you use the same name for a char[5] as you do for the function.
this is legal and won't cause any trouble as long as you don't use
any recursion. But it's terrible style and will confuse people who
are reading the code.
        for(i = 0; i <= 5; i++)
        {
               RandStr = rand() % 78;


This won't give you printable characters on any charset I've used.
(Well, /some/ will be printable. Maybe. Others will be print control
characters and beeps. Maybe.)

Consider using the RandStr() I gave you in the other thread.
        }
        return RandStr;
}

Yikes! You can't do this because RandStr[] was allocated locally
in your function - so when you return, RandStr[] dies. And you
return a pointer to it, which if used, will result in Undefined
Behavior.

If you allocated RandStr with malloc() (including <stdlib.h>!)
or passed it into the function, it would keep on living after
the function returns, and you'd be safe.

But remember to free() anything you get with malloc(), or you'll
have a memory leak on your hands.


1) Are u saying if "return RandStr" is deleted, then RandStr[] will
not die?
2) Thanks for the malloc recommendation - should it be in the main()
or as a global/static variable or inside the char *RandStr(void) ?

Thanks
 
A

Andrew Poelstra

        }
        return RandStr;
}

Yikes! You can't do this because RandStr[] was allocated locally
in your function - so when you return, RandStr[] dies. And you
return a pointer to it, which if used, will result in Undefined
Behavior.

If you allocated RandStr with malloc() (including <stdlib.h>!)
or passed it into the function, it would keep on living after
the function returns, and you'd be safe.

But remember to free() anything you get with malloc(), or you'll
have a memory leak on your hands.

1) Are u saying if "return RandStr" is deleted, then RandStr[] will
not die?
2) Thanks for the malloc recommendation - should it be in the main()
or as a global/static variable or inside the char *RandStr(void) ?

1. There are two objects here - RandStr[] and a pointer to
RandStr[]. When you write "return RandStr" your compiler
decays the array to the pointer. So the pointer that you
return keeps right on existing. What it points /at/,
however, dies when the function ends.

2. That's a design consideration. Basically, however you
malloc() it, somebody has to free() it. It depends on
your requirements how best to structure it.
 
A

Andrew Poelstra

<snip>

        }
        return RandStr;
}

Yikes! You can't do this because RandStr[] was allocated locally
in your function - so when you return, RandStr[] dies. And you
return a pointer to it, which if used, will result in Undefined
Behavior.

If you allocated RandStr with malloc() (including <stdlib.h>!)
or passed it into the function, it would keep on living after
the function returns, and you'd be safe.

But remember to free() anything you get with malloc(), or you'll
have a memory leak on your hands.

1) Are u saying if "return RandStr" is deleted, then RandStr[] will
not die?
2) Thanks for the malloc recommendation - should it be in the main()
or as a global/static variable or inside the char *RandStr(void) ?

1. There are two objects here - RandStr[] and a pointer to
RandStr[]. When you write "return RandStr" your compiler
decays the array to the pointer. So the pointer that you
return keeps right on existing. What it points /at/,
however, dies when the function ends.

2. That's a design consideration. Basically, however you
malloc() it, somebody has to free() it. It depends on
your requirements how best to structure it.

The comp.lang.c FAQ is here:
http://c-faq.com/

I highly recommend you read through that.
 
M

Mark Bluemel

On Feb 3, 8:34 pm, Andrew Poelstra <[email protected]>
wrote:
<snip>
}
return RandStr;
}
Yikes! You can't do this because RandStr[] was allocated locally
in your function - so when you return, RandStr[] dies. And you
return a pointer to it, which if used, will result in Undefined
Behavior.
If you allocated RandStr with malloc() (including <stdlib.h>!)
or passed it into the function, it would keep on living after
the function returns, and you'd be safe.
But remember to free() anything you get with malloc(), or you'll
have a memory leak on your hands.
1) Are u saying if "return RandStr" is deleted, then  RandStr[] will
not die?
2) Thanks for the malloc recommendation - should it be in the main()
or as a global/static variable or inside the char *RandStr(void) ?
1. There are two objects here - RandStr[] and a pointer to
   RandStr[]. When you write "return RandStr" your compiler
   decays the array to the pointer. So the pointer that you
   return keeps right on existing. What it points /at/,
   however, dies when the function ends.
2. That's a design consideration. Basically, however you
   malloc() it, somebody has to free() it. It depends on
   your requirements how best to structure it.

The comp.lang.c FAQ is here:
 http://c-faq.com/

I highly recommend you read through that.

I suggest he studies a decent C textbook first.
 
I

Ike Naar

{
int i;
char RandStr[5];
for(i = 0; i <= 5; i++)
{
RandStr = rand() % 78;
}
return RandStr;
}


There's another problem with the code above that hasn't been mentioned yet:
the for loop writes past the end of the array.
You probably want to replace ``<='' in the loop condition by ``<'' or ''!=''.
 
B

bartc

2005 said:
1) What is the big deal about * in front of RandStr ? - I guess it
means pointer to function - but what are the benefits?
2) If I call the RandStr in main or another function, would
char str[6];
str = RandStr
work? Why not?

char *RandStr(void)
{
int i;
char RandStr[5];
for(i = 0; i <= 5; i++)
{
RandStr = rand() % 78;
}
return RandStr;
}


This has to be some sort of puzzle? ('How many things are wrong in this
picture...')
 
M

Mark Bluemel

1) What is the big deal about * in front of RandStr ?  - I guess it
means pointer to function - but what are the benefits?
2) If I call the RandStr in main or another function, would
char str[6];
str = RandStr
work?  Why not?
char *RandStr(void)
{
       int i;
       char RandStr[5];
       for(i = 0; i <= 5; i++)
       {
              RandStr = rand() % 78;
       }
       return RandStr;
}


This has to be some sort of puzzle? ('How many things are wrong in this
picture...')


Only British TV watchers will understand why I just heard a voice
saying "little cactus"...
 
J

John Bode

1) What is the big deal about * in front of RandStr ?  - I guess it
means pointer to function - but what are the benefits?

No. "char *RandStr(void)" indicates that RandStr() returns a pointer
to char, not that RandStr is a pointer to a function.

In general:

T f() -- f is a function returning a value of type T
T *f() -- f is a function returning a value of type pointer
to T
T (*f)() -- f is a pointer to a function returning a value
of type T
T *(*f)() -- f is a pointer to a function returning a value of
type pointer to T

Similarly for arrays:

T a[N] -- a is an N-element array of type T
T *a[N] -- a is an N-element array of type pointer to T
T (*a)[N] -- a is a pointer to an N-element array of type T
T *(*a)[N] -- a is a pointer to an N-element array of type
pointer to T
2) If I call the RandStr in main or another function, would
char str[6];
str = RandStr
work?  Why not?

No. First of all, you cannot assign to an array object; the semantics
of the language forbid it. Secondly, since you left the "()" off of
the "RandStr" expression, the expression is evaluated as a pointer to
the RandStr function, rather than as a call to the RandStr function.
That would be a type mismatch, as illustrated in the table below:

Declaration Expression Expression Type Note
----------- ---------- --------------- ----
char str[6] str char [6] "decays" to char *,
but that's not
relevant
here.
str char

char *RandStr() RandStr() char * function call
RandStr char *(*)() function name treated
as pointer to
function

If RandStr() returns a pointer to a sequence of characters, and you
want to copy that sequence to str, you need to use strcpy() or
strncpy(). If you can't guarantee that all strings returned from
RandStr() will be 5 characters or less, then you need to use
strncpy():

#include <string.h>
...
char str[6];
strncpy(str, RandStr(), sizeof str - 1); // copy at most 5
characters
str[5] = 0; // make sure the string is 0-terminated;
char *RandStr(void)
{
        int i;
        char RandStr[5];
        for(i = 0; i <= 5; i++)
        {
               RandStr = rand() % 78;
        }
        return RandStr;


Several problems. First of all, it's best not to use the name of the
function as the name of a variable within the function; that way leads
to confusion. The bigger problem is returning RandStr; instead of
returning a copy of the contents of the array, the function returns
the address of the first element of the array. The problem with that
is that as soon as the function exits, the array is no longer valid;
the memory that it occupied is now available for something else to
use, and it may be overwritten before you can read it.

Finally, "rand() % 78" is not a good way to generate random
characters, especially if you want all of them to be printable.
Assuming ASCII, values 0 through 31 are control characters (including
line feeds, form feeds, tabs, bells, etc.). Printable characters
start with ' ' (ASCII 32) and run through '~' (ASCII 126). At the
very least, you'll want to replace that expression with something
like

dest = ' ' + rand() % ('~' - ' ');

It's not a *good* solution, but it at least gives you something
printable.

It's a better idea to abstract that out into a separate
RandomCharacter() function; that way you can deal with different
character sets or different locales without it affecting the RandStr
function itself.

char RandomCharacter(void)
{
/**
* There are easily a thousand better ways to
* do this that a) aren't tied to a specific
* encoding and b) offer better performance wrt
* randomization, but I've already spent more
* time on this than I should, so we'll just
* adapt your method for ASCII.
*/
char result = ' ' + rand() % ('~' - ' ');
return result;
}

Actually, for situations like this where you need to write the result
of a function into an array, it's best to pass the target array (and
its length) as parameters to the function:

void RandStr(char *dest, size_t destSize)
{
size_t i;
for (i = 0; i < destSize - 1; i++)
{
dest = RandomCharacter();
}
dest = 0; // add 0 terminator
}
...
int main(void)
{
char target[6];
RandStr(target, sizeof target);
printf("target: \"%s\"\n", target);
}
 
J

John Bode

Declaration      Expression   Expression Type   Note
-----------      ----------   ---------------   ----
char str[6]      str          char [6]          "decays" to char *,
                                                  but that's not
relevant
                                                  here.
                 str       char

char *RandStr()  RandStr()    char *            function call
                 RandStr      char *(*)()       function name treated
                                                   as pointer to
function


Argh. Way to go, GG. Let me see if I can't clean that up a bit:

Declaration Expression Expr Type Note
----------- ---------- --------- ----
char str[6] str char [6] "decays" to char *,
but that's not
relevant here.
str char

char *RandStr() RandStr() char * function call
RandStr char *(*)() function name treated
as pointer to
function
 
B

Barry Schwarz

1) What is the big deal about * in front of RandStr ?  - I guess it
means pointer to function - but what are the benefits?

Nope - it means that instead of returning a char, you're
returning a pointer to char. A very different beast.
2) If I call the RandStr in main or another function, would
char str[6];
str = RandStr

Without the mandatory () empty argument list, this is not even a
function call.
work?  Why not?

No, because you can't assign to arrays directly like that. There
was another thread about exactly this earlier today; see if you
can find it on groups.google.com or something.
char *RandStr(void)
{
        int i;
        char RandStr[5];

Here you use the same name for a char[5] as you do for the function.
this is legal and won't cause any trouble as long as you don't use
any recursion. But it's terrible style and will confuse people who
are reading the code.
        for(i = 0; i <= 5; i++)
        {
               RandStr = rand() % 78;


This won't give you printable characters on any charset I've used.
(Well, /some/ will be printable. Maybe. Others will be print control
characters and beeps. Maybe.)

Consider using the RandStr() I gave you in the other thread.
        }
        return RandStr;
}

Yikes! You can't do this because RandStr[] was allocated locally
in your function - so when you return, RandStr[] dies. And you
return a pointer to it, which if used, will result in Undefined
Behavior.

If you allocated RandStr with malloc() (including <stdlib.h>!)
or passed it into the function, it would keep on living after
the function returns, and you'd be safe.

But remember to free() anything you get with malloc(), or you'll
have a memory leak on your hands.


1) Are u saying if "return RandStr" is deleted, then RandStr[] will
not die?


Using the same name for a function and an array just makes the
conversation unnecessarily confusing.

The array is an automatic array local to the function. It comes into
being when the function is called and ceases to exist when the
function exits. Returning or not returning its address does not
affect its lifespan at all. The point being made was that once the
array dies, its address no longer has any meaning and attempting to
use it for any purpose invokes undefined behavior.

But if you delete the return statement, you have the equally obnoxious
mistake of not returning a value from a function defined to return
one. Any attempt to use the return value in the calling function when
the function didn't actually return one invokes undefined behavior.
2) Thanks for the malloc recommendation - should it be in the main()
or as a global/static variable or inside the char *RandStr(void) ?

Why did you interject a completely unrelated issue such as global
variables?

If you call malloc in main, you will need to pass the resulting
address to your function. If you call malloc in the function, you
will need to return the resulting address to the caller and let that
function free it when it is no longer needed.
 

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,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top