a question of style

Discussion in 'C Programming' started by questions?, Feb 28, 2006.

  1. questions?

    questions? Guest

    I am curious about whether I should do this

    say I want to calculate dot product of two matrix(4X4,fixed)
    I do two ways

    1)
    void dot_product(double A[4][4] , double B[4][4], double result[4][4]){
    blah blah

    }

    my results are automatically given back in the matrix result[4][4]

    or

    2)
    double [4][4] dot_product(double A[4][4],double B[4][4]){
    double result[4][4];
    blah blah

    return result;
    }

    for the second type, result is local variable and will be released
    after function call, Will the program have problem to access?

    Are there better and neat way to this problem?

    Thanks
     
    questions?, Feb 28, 2006
    #1
    1. Advertisements

  2. questions?

    Artie Gold Guest

    Well since option 2 is not an option at all (arrays are not a first
    class type in C, so an array cannot be a return value), you're left with
    option 1.

    The other option would be to wrap your array in a struct and return
    *that*, but that would depend upon how you plan on using this code...

    BTW - explicitly mentioning the first dimension of a passed array is
    superfluous; i.e. `double A[][4]' and `double A[4][4]' -- or for that
    matter double A[400][4] -- mean the same thing.

    HTH,
    --ag
     
    Artie Gold, Feb 28, 2006
    #2
    1. Advertisements

  3. questions?

    questions? Guest

    I see, I see.
    but Do you have the same problem?

    Say you locally define a structure which has the array you want to
    return.
    when you return that, you are pointing to a local variable which will
    be released?

    Thanks a lot
     
    questions?, Feb 28, 2006
    #3
  4. questions?

    Artie Gold Guest

    No, you'd receive, as a return value, a *copy* of the local structure --
    albeit a shallow copy.

    HTH,
    --ag
     
    Artie Gold, Feb 28, 2006
    #4
  5. questions?

    Micah Cowan Guest

    Only if you return a /pointer/ to the struct. That's not what he's
    recommending. He's saying, if you want, you can return the struct
    itself. And he doesn't mean locally define the structure: it will have
    to have a filescope definition, in order to declare it as the
    function's return type.

    Returning a struct involves an implicit copy of your local value
    into a value that gets passed back to the caller as the return value.

    -Micah
     
    Micah Cowan, Feb 28, 2006
    #5
  6. questions?

    Default User Guest

    Only if you returned a pointer. With the struct variant, you return the
    struct, so a copy is made of it. There's no pointer to a local variable
    the way there can be with an array.


    Brian
     
    Default User, Feb 28, 2006
    #6
  7. Since both sizes of these arrays are fixed, when using this approach I'd declare
    the function as follows

    void dot_product(const double (*A)[4][4], const double (*B)[4][4],
    double (*result)[4][4])
    {
    /* ... */
    }

    In my opinion, use of "decayed" pointers to pass arrays should be limited to
    situations when array size is expected to vary.
     
    Andrey Tarasevich, Feb 28, 2006
    #7
  8. questions?

    Pedro Graca Guest

    What do you mean with "a shallow copy"?

    My test worked fine:


    #include <stdio.h>

    struct Arr {
    int array[100];
    };

    struct Arr ret_struct(void) {
    struct Arr foo = {{0}};
    foo.array[0] = 1000;
    foo.array[99] = 42;
    return foo;
    }

    int main(void) {
    struct Arr arr;

    arr = ret_struct();
    printf("%d, %d (repeated 98 times), %d\n",
    arr.array[0], arr.array[50], arr.array[99]);
    return 0;
    }
     
    Pedro Graca, Mar 1, 2006
    #8
  9. If your structure contains pointers, the copy will contain copies of
    those pointers (pointing to the same objects); any data outside the
    structure itself won't be copied.

    For example, suppose you have a struct representing a variable-length
    string:

    struct my_string {
    size_t len;
    char *str;
    };

    struct my_string s1, s2;
    s1.len = 6;
    s1.str = malloc(6); /* should check for errors here */
    strcpy(s1.str, "hello");

    Then this:

    s2 = s1;

    creates a shallow copy of s1. s1.str and s2.str point to the same
    shared object; changing the string pointed to by s2.str will also
    change the string pointed to by s1.str:

    s2.str[0] = 'H';
    /* now s1.str and s2.str both point to "Hello" */

    By contrast, a deep copy creates a new copy of any pointed-to data
    as well as of the structure itself:

    s2.len = s1.len;
    s2.str = malloc(s1.len); /* again, should check for error here */
    memcpy(s2.str, s1.str, s1.len);

    Now s1.str and s2.str point to distinct objects, and changing one
    won't affect the other:

    s2.str[0] = 'H';

    /* now s2.str points to "Hello", but
    s1.str still points to "hello" */

    A deep copy requires knowing the contents of the structure. In more
    complex cases, it may require recursing to other nodes (think about
    making a deep copy of a binary tree).

    Often a shallow copy is good enough -- which is fortunate, because a
    deep copy requires substantially more work.
     
    Keith Thompson, Mar 1, 2006
    #9
  10. questions?

    Micah Cowan Guest

    What he means is that if your struct has a pointer in it, that will be
    copied over unchanged. So, for example:

    #include <stdio.h>
    #define ELMS_IN_ARY(a) (sizeof (a) / sizeof (a)[0])

    struct foo {
    int a[3];
    char *b;
    };

    struct foo foo_maker(void)
    {
    char phrase[] = "D@mn it feels good to be a gangsta.";
    struct foo retval = { {0, 1, 3}, phrase };

    return retval;
    }

    int main(void)
    {
    struct foo doo;
    int *cur, *end;

    doo = foo_maker();
    for (cur = &doo.a[0], end = cur + ELMS_IN_ARY(doo.a); cur != end; ++cur)
    printf("%d\n", *cur);

    printf("%s\n", doo.b);
    return 0;
    }

    retval.a's elements will be copied into doo.a. However, the exact
    pointer value contained in retval.b will also be copied over exactly
    to doo.b, but after foo_maker() has exited, that value is invalid;
    thus the second printf() statement in main() invokes undefined
    behavior.

    -Micah
     
    Micah Cowan, Mar 1, 2006
    #10
  11. questions?

    Pedro Graca Guest

    <snip>

    Thank you very much for the excellent explanation -- I almost didn't
    snip it: it deserves being repeated :).
     
    Pedro Graca, Mar 1, 2006
    #11
  12. questions?

    Thad Smith Guest

    Excellent suggestion!
     
    Thad Smith, Mar 1, 2006
    #12
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.