Returning values from a function

Discussion in 'C Programming' started by Materialised, Oct 20, 2003.

  1. Materialised

    Materialised Guest

    I am writing a simple function to initialise 3 variables to pesudo
    random numbers.

    I have a function which is as follows

    int randomise( int x, int y, intz)
    {
    srand((unsigned)time(NULL));
    x = rand();
    y = rand();
    z = rand();

    }
    And I call this function with

    randomise(a,b,c);

    However a,b,c do not contain the randomised integers, I understand this
    is a problem with the return value of my function,
    I have tried
    return x,y,z;
    But this doesnt work either.

    Can anyone point out where my problem is?
     
    Materialised, Oct 20, 2003
    #1
    1. Advertising

  2. Materialised

    WW Guest

    Materialised wrote:
    > I am writing a simple function to initialise 3 variables to pesudo
    > random numbers.
    >
    > I have a function which is as follows
    >
    > int randomise( int x, int y, intz)
    > {
    > srand((unsigned)time(NULL));
    > x = rand();
    > y = rand();
    > z = rand();
    >
    > }
    > And I call this function with
    >
    > randomise(a,b,c);
    >
    > However a,b,c do not contain the randomised integers, I understand
    > this is a problem with the return value of my function,
    > I have tried
    > return x,y,z;
    > But this doesnt work either.
    >
    > Can anyone point out where my problem is?


    Ehem. The first one is that you try to program in C++ without a good
    textbook. :-(

    First of all, your program has not return value. You do not return
    anything. There is no return statement.

    The second: how do you expect to return 3 integers in one?

    The third: as you wrote the function definition (signature) it takes the
    arguments by value, so x,y and z (which you have clearly typed wrong) is a
    *copy* of a b and c. Writing into them will write into the copy.

    You can take the arguments by reference, then you will be able to change
    them. *If* you work in C++. If you do work in C, you will need to take
    pointers to them.

    --
    WW aka Attila
     
    WW, Oct 20, 2003
    #2
    1. Advertising

  3. Materialised

    Eric Sosman Guest

    Materialised wrote:
    >
    > I am writing a simple function to initialise 3 variables to pesudo
    > random numbers.
    >
    > I have a function which is as follows
    >
    > int randomise( int x, int y, intz)
    > {
    > srand((unsigned)time(NULL));
    > x = rand();
    > y = rand();
    > z = rand();
    >
    > }
    > And I call this function with
    >
    > randomise(a,b,c);
    >
    > However a,b,c do not contain the randomised integers, I understand this
    > is a problem with the return value of my function,
    > I have tried
    > return x,y,z;
    > But this doesnt work either.
    >
    > Can anyone point out where my problem is?


    These are Questions 4.8 and 20.1 in the comp.lang.c
    Frequently Asked Questions (FAQ) list

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

    --
     
    Eric Sosman, Oct 20, 2003
    #3
  4. Materialised wrote:

    > I am writing a simple function to initialise 3 variables to pesudo
    > random numbers.
    >
    > I have a function which is as follows
    >
    > int randomise( int x, int y, intz)
    > {
    > srand((unsigned)time(NULL));
    > x = rand();
    > y = rand();
    > z = rand();
    >
    > }
    > And I call this function with
    >
    > randomise(a,b,c);
    >
    > However a,b,c do not contain the randomised integers, I understand this
    > is a problem with the return value of my function,
    > I have tried
    > return x,y,z;
    > But this doesnt work either.
    >
    > Can anyone point out where my problem is?


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

    void randomise(int *x, int *y, int *z)
    {
    srand((unsigned) time(NULL));
    *x = rand();
    *y = rand();
    *z = rand();
    }

    int main(void)
    {
    int a, b, c;
    randomise(&a, &b, &c);
    printf("%d %d %d\n", a, b, c);
    return 0;
    }





    --
    Martin Ambuhl
     
    Martin Ambuhl, Oct 20, 2003
    #4
  5. Materialised

    Materialised Guest

    WW wrote:
    > Materialised wrote:
    >
    >>I am writing a simple function to initialise 3 variables to pesudo
    >>random numbers.
    >>
    >>I have a function which is as follows
    >>
    >>int randomise( int x, int y, intz)
    >>{
    >>srand((unsigned)time(NULL));
    >>x = rand();
    >>y = rand();
    >>z = rand();
    >>
    >>}
    >>And I call this function with
    >>
    >>randomise(a,b,c);
    >>
    >>However a,b,c do not contain the randomised integers, I understand
    >>this is a problem with the return value of my function,
    >>I have tried
    >>return x,y,z;
    >>But this doesnt work either.
    >>
    >>Can anyone point out where my problem is?

    >
    >
    > Ehem. The first one is that you try to program in C++ without a good
    > textbook. :-(
    >
    > First of all, your program has not return value. You do not return
    > anything. There is no return statement.
    >
    > The second: how do you expect to return 3 integers in one?
    >
    > The third: as you wrote the function definition (signature) it takes the
    > arguments by value, so x,y and z (which you have clearly typed wrong) is a
    > *copy* of a b and c. Writing into them will write into the copy.
    >
    > You can take the arguments by reference, then you will be able to change
    > them. *If* you work in C++. If you do work in C, you will need to take
    > pointers to them.
    >

    Thanks for your help, I realised my error right after posting

    int randomise()
    {
    int x;
    srand((unsigned)time(NULL));
    x = rand();
    return x;
    }

    and in main

    a = randomise();
    b = randomise();
    c = randomise();
     
    Materialised, Oct 20, 2003
    #5
  6. Materialised

    Artie Gold Guest

    Materialised wrote:
    > WW wrote:
    >
    >> Materialised wrote:
    >>
    >>> I am writing a simple function to initialise 3 variables to pesudo
    >>> random numbers.
    >>>
    >>> I have a function which is as follows
    >>>
    >>> int randomise( int x, int y, intz)
    >>> {
    >>> srand((unsigned)time(NULL));
    >>> x = rand();
    >>> y = rand();
    >>> z = rand();
    >>>
    >>> }
    >>> And I call this function with
    >>>
    >>> randomise(a,b,c);
    >>>
    >>> However a,b,c do not contain the randomised integers, I understand
    >>> this is a problem with the return value of my function,
    >>> I have tried
    >>> return x,y,z;
    >>> But this doesnt work either.
    >>>
    >>> Can anyone point out where my problem is?

    >>
    >>
    >>
    >> Ehem. The first one is that you try to program in C++ without a good
    >> textbook. :-(
    >>
    >> First of all, your program has not return value. You do not return
    >> anything. There is no return statement.
    >>
    >> The second: how do you expect to return 3 integers in one?
    >>
    >> The third: as you wrote the function definition (signature) it takes the
    >> arguments by value, so x,y and z (which you have clearly typed wrong) is a
    >> *copy* of a b and c. Writing into them will write into the copy.
    >>
    >> You can take the arguments by reference, then you will be able to change
    >> them. *If* you work in C++. If you do work in C, you will need to take
    >> pointers to them.
    >>

    > Thanks for your help, I realised my error right after posting
    >
    > int randomise()
    > {
    > int x;
    > srand((unsigned)time(NULL));
    > x = rand();
    > return x;
    > }
    >
    > and in main
    >
    > a = randomise();
    > b = randomise();
    > c = randomise();
    >


    No, you don't want to do that either.
    Calling `srand()' multiple times like that (i.e. for each call to
    `rand()') will not make the numbers any more random, and may do
    exactly the opposite.

    Call srand() once...

    ....and please reread the suggestions elsethread.

    HTH,
    --ag

    --
    Artie Gold -- Austin, Texas
    Oh, for the good old days of regular old SPAM.
     
    Artie Gold, Oct 20, 2003
    #6
  7. Materialised

    Dan Pop Guest

    In <bn11p3$rv6a4$-berlin.de> Materialised <> writes:

    >I am writing a simple function to initialise 3 variables to pesudo
    >random numbers.
    >
    >I have a function which is as follows
    >
    >int randomise( int x, int y, intz)
    >{
    >srand((unsigned)time(NULL));
    >x = rand();
    >y = rand();
    >z = rand();
    >
    >}
    >And I call this function with
    >
    >randomise(a,b,c);
    >
    >However a,b,c do not contain the randomised integers, I understand this
    >is a problem with the return value of my function,
    >I have tried
    >return x,y,z;
    >But this doesnt work either.
    >
    >Can anyone point out where my problem is?


    Sure, both your favourite C book and the FAQ can.

    The *right* way of solving this problem in C is by using a structure:

    struct random { int x, y, z; };

    struct random randomise(void)
    {
    struct random t;
    srand((unsigned)time(NULL)); /* this function call doesn't belong
    here, unless you call this function exactly once */
    t.x = rand();
    t.y = rand();
    t.z = rand();
    return t;
    }

    Ignore any advice recommending the usage of three pointers in the
    function's interface. Such interfaces are evil, in general, even if, in
    this particular case, there is no big deal. Functions should not use
    their parameters as a way of returning back information to the caller.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Oct 20, 2003
    #7
  8. Materialised

    Default User Guest

    WW wrote:

    > Ehem. The first one is that you try to program in C++ without a good
    > textbook. :-(



    C++
     
    Default User, Oct 20, 2003
    #8
  9. Materialised

    Default User Guest

    WW wrote:

    > You can take the arguments by reference, then you will be able to change
    > them. *If* you work in C++. If you do work in C, you will need to take
    > pointers to them.



    Where did the OP say he was working in C++?




    Brian Rodenborn
     
    Default User, Oct 20, 2003
    #9
  10. In comp.lang.c Dan Pop <> wrote:

    > Ignore any advice recommending the usage of three pointers in the
    > function's interface. Such interfaces are evil, in general, even if, in
    > this particular case, there is no big deal. Functions should not use
    > their parameters as a way of returning back information to the caller.


    Why is this? In what circumstances can pointers lead to tragedy?

    --
    Christopher Benson-Manica | I *should* know what I'm talking about - if I
    ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
     
    Christopher Benson-Manica, Oct 20, 2003
    #10
  11. Materialised <> writes:
    [...]
    > Thanks for your help, I realised my error right after posting
    >
    > int randomise()
    > {
    > int x;
    > srand((unsigned)time(NULL));
    > x = rand();
    > return x;
    > }
    >
    > and in main
    >
    > a = randomise();
    > b = randomise();
    > c = randomise();


    As someone else pointed out, you don't want to call srand() more than
    once in your program. You can either call it once in your main
    program, or use a static variable in randomise() to allow randomise()
    to call srand() only the first time. Calling it in main() is the
    simplest approach, but putting the srand() call inside randomise()
    might be better in terms of program organization.

    Also, the way your randomise() function is now written, the variable x
    is unnecessary. Assuming you call srand() from main(), randomise()
    could look like this:

    int randomise(void)
    {
    int x;
    x = rand();
    return x;
    }

    which is equivalent to this:

    int randomise(void)
    {
    return rand();
    }

    which means you probably might as well eliminate the randomise() function
    altogether:

    #include yadda yadda

    int main(void)
    {
    srand((unsigned)time(NULL));
    a = rand();
    b = rand();
    c = rand();
    ...
    }

    A couple more things to note:

    C library implementations of rand() are often of poor quality; there
    might be a system-specific routine that gives you better random
    numbers.

    The values return by rand() are in the range 0 .. RAND_MAX (defined in
    <stdlib.h>). You probably want some range that you specify; see
    question 13.16 in the C FAQ for details.

    Given these complications, getting a useful random number is going to
    involve more than just calling rand(), and you probably do want
    something like your randomise() function.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
    Schroedinger does Shakespeare: "To be *and* not to be"
     
    Keith Thompson, Oct 20, 2003
    #11
  12. Materialised

    Materialised Guest

    Materialised wrote:
    > I am writing a simple function to initialise 3 variables to pesudo
    > random numbers.
    >
    > I have a function which is as follows
    >
    > int randomise( int x, int y, intz)
    > {
    > srand((unsigned)time(NULL));
    > x = rand();
    > y = rand();
    > z = rand();
    >
    > }
    > And I call this function with
    >
    > randomise(a,b,c);
    >
    > However a,b,c do not contain the randomised integers, I understand this
    > is a problem with the return value of my function,
    > I have tried
    > return x,y,z;
    > But this doesnt work either.
    >
    > Can anyone point out where my problem is?
    >

    I would like to thank everyone for their input on this matter.

    I have been given a few solutions, using pointers, eliminating the
    random function altogether, using a structure, etc, etc.

    My question now is which of these solutions would be more efficient?
    Or is this compiler dependent and considered OT?
    (Dont wanna be flamed)
     
    Materialised, Oct 21, 2003
    #12
  13. Materialised wrote:
    >
    >
    > I have been given a few solutions, using pointers, eliminating the
    > random function altogether, using a structure, etc, etc.
    >
    > My question now is which of these solutions would be more efficient?
    > Or is this compiler dependent and considered OT?
    > (Dont wanna be flamed)


    Sorry. Can't resist.
    Why is it that newbies who are berely able to write a correct
    program always care about efficiency.
    To say it clearly: Forget about efficiency for now at this level.
    Write your program correct, make it work. Then watch your
    program. If it is fast enough: don't do anything. If not: profile!
    and figure out where time is spent. Only after you know where your
    program uses up the time you care about efficiency.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, Oct 21, 2003
    #13
  14. Materialised

    Dan Pop Guest

    In <bn18om$pmb$> Christopher Benson-Manica <> writes:

    >In comp.lang.c Dan Pop <> wrote:
    >
    >> Ignore any advice recommending the usage of three pointers in the
    >> function's interface. Such interfaces are evil, in general, even if, in
    >> this particular case, there is no big deal. Functions should not use
    >> their parameters as a way of returning back information to the caller.

    >
    >Why is this? In what circumstances can pointers lead to tragedy?


    In most cases, using pointer arguments this way results in less readable
    and maintainable code. It's not clear whether the callee will use the
    existing values of the pointed-to objects or whether it will
    unconditionally change them. When encountering such a function call,
    you *must* study its definition, to see what exactly is happening.
    Functions not taking pointers to scalars as their arguments don't raise
    such issues, you can safely ignore their definitions if they are not
    directly relevant to the issue you're currently investigating.

    To be more clear, I'm talking about returning back scalar information to
    the caller. It is perfectly OK to do it for arrays. So, in the case of
    the OP, another valid solution would be

    void randomise(int *array);

    where the caller is passing the address of the first int in an array
    of three int's.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Oct 21, 2003
    #14
  15. In alt.comp.lang.learn.c-c++ Dan Pop <> wrote:
    > In most cases, using pointer arguments this way results in less readable
    > and maintainable code. It's not clear whether the callee will use the
    > existing values of the pointed-to objects or whether it will
    > unconditionally change them. When encountering such a function call,
    > you *must* study its definition, to see what exactly is happening.
    > Functions not taking pointers to scalars as their arguments don't raise
    > such issues, you can safely ignore their definitions if they are not
    > directly relevant to the issue you're currently investigating.
    >
    > To be more clear, I'm talking about returning back scalar information to
    > the caller. It is perfectly OK to do it for arrays. So, in the case of
    > the OP, another valid solution would be
    >
    > void randomise(int *array);
    >
    > where the caller is passing the address of the first int in an array
    > of three int's.


    And how do you tell on the caller side that the function
    (a) does not use the values in *array, *(array + 1), *(array + 2)
    (b) puts something in there
    (c) uses three items?

    This solution is as good or as bad as passing three separate pointers.
    I'd even argue it is worse as (c) is non-obvious.

    Andre'
     
    =?iso-8859-1?Q?Andr=E9_P=F6nitz?=, Oct 21, 2003
    #15
  16. Materialised

    Dan Pop Guest

    In <bn36ou$re0$-chemnitz.de> =?iso-8859-1?Q?Andr=E9_P=F6nitz?= <> writes:

    >In alt.comp.lang.learn.c-c++ Dan Pop <> wrote:
    >> In most cases, using pointer arguments this way results in less readable
    >> and maintainable code. It's not clear whether the callee will use the
    >> existing values of the pointed-to objects or whether it will
    >> unconditionally change them. When encountering such a function call,
    >> you *must* study its definition, to see what exactly is happening.
    >> Functions not taking pointers to scalars as their arguments don't raise
    >> such issues, you can safely ignore their definitions if they are not
    >> directly relevant to the issue you're currently investigating.
    >>
    >> To be more clear, I'm talking about returning back scalar information to
    >> the caller. It is perfectly OK to do it for arrays. So, in the case of
    >> the OP, another valid solution would be
    >>
    >> void randomise(int *array);
    >>
    >> where the caller is passing the address of the first int in an array
    >> of three int's.

    >
    >And how do you tell on the caller side that the function
    > (a) does not use the values in *array, *(array + 1), *(array + 2)
    > (b) puts something in there
    > (c) uses three items?


    The function's prototype clearly suggests that the function is using the
    pointer in write mode. And, if the array is not already initialised,
    it is a (relatively) safe bet that it ignores the existing contents.

    If this is not enough for your immediate needs, you can always check the
    function definition.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Oct 21, 2003
    #16
  17. In alt.comp.lang.learn.c-c++ Dan Pop <> wrote:
    >>> To be more clear, I'm talking about returning back scalar information to
    >>> the caller. It is perfectly OK to do it for arrays. So, in the case of
    >>> the OP, another valid solution would be
    >>>
    >>> void randomise(int *array);
    >>>
    >>> where the caller is passing the address of the first int in an array
    >>> of three int's.

    >>
    >>And how do you tell on the caller side that the function
    >> (a) does not use the values in *array, *(array + 1), *(array + 2)
    >> (b) puts something in there
    >> (c) uses three items?

    >
    > The function's prototype clearly suggests that the function is using the
    > pointer in write mode.


    I see no particular difference between

    void func(int *item1, int *item2, int *item3);

    void foo()
    {
    int i1, i2, i3;
    func(&i1, &i2, &i3);
    }

    and

    void func(int *arr);

    void foo()
    {
    int arr[3];
    func(arr);
    }

    at least noct to a degree to call the seond version "safer".


    > And, if the array is not already initialised,
    > it is a (relatively) safe bet that it ignores the existing contents.


    So when I debug code and see the caller side I have to assume it is
    correct to make a guess on how the function works?

    This is not different from the original proposal.

    > If this is not enough for your immediate needs, you can always check the
    > function definition.


    I thought your main point was that your solution makes checking the
    definition unnecessary.

    I am still not convinced and still maintain that your solution is not
    better than the original. But maybe I simply don't

    Andre'

    --
    Those who desire to give up Freedom in order to gain Security, will not have,
    nor do they deserve, either one. (T. Jefferson or B. Franklin or both...)
     
    =?iso-8859-1?Q?Andr=E9_P=F6nitz?=, Oct 21, 2003
    #17
  18. On Tue, 21 Oct 2003 10:03:24 +0200, Karl Heinz Buchegger wrote:

    >
    >
    > Materialised wrote:
    >>
    >>
    >> I have been given a few solutions, using pointers, eliminating the
    >> random function altogether, using a structure, etc, etc.
    >>
    >> My question now is which of these solutions would be more efficient?
    >> Or is this compiler dependent and considered OT?
    >> (Dont wanna be flamed)

    >
    > Sorry. Can't resist.
    > Why is it that newbies who are berely able to write a correct
    > program always care about efficiency.
    > To say it clearly: Forget about efficiency for now at this level.
    > Write your program correct, make it work. Then watch your
    > program. If it is fast enough: don't do anything. If not: profile!
    > and figure out where time is spent. Only after you know where your
    > program uses up the time you care about efficiency.


    And nine out of ten, the speedup comes from rewriting algorithms, not
    technical details.

    I'm not saying technical details can't make a difference, just that they
    are in the order of a few percent most of the time.

    M4
     
    Martijn Lievaart, Oct 21, 2003
    #18
  19. On Tue, 21 Oct 2003 10:49:58 +0000, Dan Pop wrote:

    > To be more clear, I'm talking about returning back scalar information to
    > the caller. It is perfectly OK to do it for arrays. So, in the case of
    > the OP, another valid solution would be
    >
    > void randomise(int *array);
    >
    > where the caller is passing the address of the first int in an array
    > of three int's.


    I'ld always do this as

    void randomise(int *array, int size);

    HTH,
    M4
     
    Martijn Lievaart, Oct 21, 2003
    #19
  20. On Tue, 21 Oct 2003, Dan Pop wrote:
    >
    > Christopher Benson-Manica <> writes:
    > >In comp.lang.c Dan Pop <> wrote:
    > >
    > >> Ignore any advice recommending the usage of three pointers in the
    > >> function's interface. Such interfaces are evil, in general, even if, in
    > >> this particular case, there is no big deal. Functions should not use
    > >> their parameters as a way of returning back information to the caller.

    > >
    > >Why is this? In what circumstances can pointers lead to tragedy?

    >
    > In most cases, using pointer arguments this way results in less readable
    > and maintainable code.


    While this is true, I must respectfully disagree with most of the
    rest of what you're saying.

    > It's not clear whether the callee will use the
    > existing values of the pointed-to objects or whether it will
    > unconditionally change them. When encountering such a function call,
    > you *must* study its definition, to see what exactly is happening.


    ....unless the pointer parameters have 'const' attached to them in
    the right places, so you can tell they're not being changed. If
    they're *not* constified, then it's almost always better to assume
    they *will* be changed. (No guarantees, though.)

    > To be more clear, I'm talking about returning back scalar information to


    s/returning back/returning/

    > the caller. It is perfectly OK to do it for arrays. So, in the case of
    > the OP, another valid solution would be
    >
    > void randomise(int *array);
    >
    > where the caller is passing the address of the first int in an array
    > of three int's.


    I think this is worse than the original for *several* reasons.

    void foo(int *bar);

    is the accepted idiom for "bar is an array of int," with no constness
    guarantees either way; it's rare IME to see

    void foo(const int *bar);

    So just by looking at the prototype, the client can't tell as reliably
    whether the value of *bar will be changed.

    void foo(const int bar[3]);

    would be preferable in this case, since it specifies that we need to
    pass exactly 3 integers in the array -- not 2, not 4, but 3. Doesn't
    help the compiler, but it can help the client.

    Finally, I think that the average programmer is likely to find the
    array-based solution simply too clumsy. It takes time and LOC to
    initialize an array that would be slightly less annoying to do with
    single ints. Unless, of course, the parameters are part of a larger
    "chunk" of information (say, the XYZ coordinates of a point), in
    which case it probably makes more sense to pass around a (pointer to
    a) 'struct'.

    When I see

    int a, b, c;
    ...
    foo(&a, &b, &c);

    it's pretty obvious that something is going to get changed inside
    foo. In contrast, when I see

    int r[3];
    ...
    foo(r);

    I can't even tell without checking types again that r *is* getting
    "passed by pointer." I think that's more of a disadvantage than
    whatever advantages you see to the lack of & operators -- I consider
    &s a red flag!

    Just for completeness, what do you think of

    void foo(int (*bar)[3]);

    int r[3];
    ...
    foo(&r);

    ?
    (I think it's unnecessarily ugly and restrictive, myself.)

    -Arthur
     
    Arthur J. O'Dwyer, Oct 21, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jorgen Gustafsson
    Replies:
    4
    Views:
    607
    Jorgen Gustafsson
    Dec 12, 2003
  2. Replies:
    4
    Views:
    293
    Dennis Lee Bieber
    Feb 12, 2005
  3. arnuld
    Replies:
    10
    Views:
    597
    Jerry Coffin
    Aug 25, 2007
  4. Replies:
    6
    Views:
    388
  5. Karlo Lozovina
    Replies:
    5
    Views:
    385
    Gabriel Genellina
    Mar 10, 2008
Loading...

Share This Page