Re: What have we done wrong in this code sample please

Discussion in 'C Programming' started by Claire, Jun 25, 2003.

  1. Claire

    Claire Guest


    > You have given us incomplete and non-standard code - present a minimal but
    > compilable code fragment using no non-standard extensions that
    > demonstrates the problem, and we may be able to help.
    > --
    > Freenet distribution not available


    Sorry about that fellas, how's the stripped following as an alternative?
    I guess Im stuck on how to pass the PRecipe record pointer field to my
    TestFunc properly.
    Can you help please. Ive still not got it right.


    typedef struct
    {
    // all other fields removed
    char pszStartStr[6][21];// An array of 6 strings, each one 20 chars plus
    terminating character
    }TRecipe;
    typedef TRecipe *PRecipe;


    char *s1[2] = {"s1_0","s1_1"};
    char *s2[2][2]={"s2_00","s2_01","s2_10","s2_11"};

    bool PlaceText(char nRow, char nColumn, char *pszText)// writes string to
    display
    {
    //foobar;
    return 1;
    }

    void TestFunc(char **Str)
    {
    PlaceText(1,1,(char*)Str[0]);// 1st item in list of strings
    PlaceText(2,1,(char*)Str[1]);// 2nd item in list of strings
    }

    void main(void)
    {
    PRecipe pRecipe;
    TRecipe Recipe;

    pRecipe = &Recipe;// Temporary test variable

    strcpy(Recipe.pszStartStr[0], "Hello");
    strcpy(Recipe.pszStartStr[1], "Goodbye");

    TestFunc(s1); // this one works
    TestFunc(s2[0]); // this one works

    //TestFunc(pRecipe->pszStartStr[0]);
    //TestFunc(&pRecipe->pszStartStr[0]);
    //TestFunc((char**)(pRecipe->pszStartStr[0]));
    // All 3 of the above are abysmal attempts to pass an arrayed string field
    from a record pointer and none work
    }
     
    Claire, Jun 25, 2003
    #1
    1. Advertising

  2. On Wed, 25 Jun 2003, Claire wrote:
    >
    > Sorry about that fellas, how's the stripped following as an alternative?
    > I guess Im stuck on how to pass the PRecipe record pointer field to my
    > TestFunc properly.
    > Can you help please. Ive still not got it right.
    >
    > typedef struct
    > {
    > char pszStartStr[6][21];
    > }TRecipe;
    > typedef TRecipe *PRecipe;


    Note that I've stripped all of your C99-style comments.
    Not only will they keep your code from compiling on any
    popular compiler in conforming mode, but they were supremely
    dumb comments in the first place. We can *see* how many
    characters are in array pszStartStr[0] -- we don't need
    a comment to tell us that!

    >
    > char *s1[2] = {"s1_0","s1_1"};
    > char *s2[2][2]={"s2_00","s2_01","s2_10","s2_11"};
    >
    > void TestFunc(char **Str)
    > {
    > PlaceText(1,1,(char*)Str[0]);
    > PlaceText(2,1,(char*)Str[1]);


    Both casts to (char *) are useless. Think about it -- if Str is
    a pointer to pointer to char, then what's Str[0]? It's a pointer
    to char. The cast buys you nothing except extra typing and code
    clutter.

    > }
    >
    > void main(void)


    int main(void)

    > {
    > PRecipe pRecipe;
    > TRecipe Recipe;
    >
    > pRecipe = &Recipe;
    >
    > strcpy(Recipe.pszStartStr[0], "Hello");
    > strcpy(Recipe.pszStartStr[1], "Goodbye");
    >
    > TestFunc(s1); // this one works
    > TestFunc(s2[0]); // this one works
    >
    > //TestFunc(pRecipe->pszStartStr[0]);


    pRecipe->pszStartStr[0] is an array[21] of char; decays to (char *).

    > //TestFunc(&pRecipe->pszStartStr[0]);


    &pRecipe->pszStartStr[0] is a pointer to array[21] of char.

    > //TestFunc((char**)(pRecipe->pszStartStr[0]));


    pRecipe->pszStartStr[0] decays to (char *),
    and then you cast it to (char **). That will never work.
    Casting in ignorance doesn't solve anything.

    > // All 3 of the above are abysmal attempts to pass an arrayed string field
    > from a record pointer and none work


    *That* was a somewhat useful comment!


    char *temp = pszStartStr[0];
    TestFunc(&temp);

    /* &temp is a pointer to a pointer to char */

    Anyway, it would be simpler just to re-write your TestFunc()
    code so that it takes two (char *) arguments, or re-write your
    data structures so they contain arrays of (char *), rather than
    arrays of (char[21]).

    return 0;
    > }


    HTH
    -Arthur
     
    Arthur J. O'Dwyer, Jun 25, 2003
    #2
    1. Advertising

  3. Claire

    Claire Guest

    Many thanks for giving me your time Arthur

    > Note that I've stripped all of your C99-style comments.
    > Not only will they keep your code from compiling on any
    > popular compiler in conforming mode, but they were supremely
    > dumb comments in the first place. We can *see* how many
    > characters are in array pszStartStr[0] -- we don't need
    > a comment to tell us that!


    As a newby, I assume you mean /**/ is the standard. Sorry about that, we
    turn // on asap on our compiler options.
    Re "dumb" comments. "You" will fully understand, as you are clearly an
    expert at this, but do you know if "I" understand?
    I comment to show how Im thinking, not to explain to you. If I were
    mentoring I'd find it valuable to see my students thought processes written
    down.

    > > void TestFunc(char **Str)
    > > {
    > > PlaceText(1,1,(char*)Str[0]);
    > > PlaceText(2,1,(char*)Str[1]);

    >
    > Both casts to (char *) are useless. Think about it -- if Str is
    > a pointer to pointer to char, then what's Str[0]? It's a pointer
    > to char. The cast buys you nothing except extra typing and code
    > clutter.

    Yes, sorry, I appreciate that. Ive been testing it within our project that
    has overrides to the common variable types and forgot to remove the casts.

    >
    > char *temp = pszStartStr[0];
    > TestFunc(&temp);
    >
    > /* &temp is a pointer to a pointer to char */
    >
    > Anyway, it would be simpler just to re-write your TestFunc()
    > code so that it takes two (char *) arguments, or re-write your
    > data structures so they contain arrays of (char *), rather than
    > arrays of (char[21]).

    Yes it would be simpler, but that is a test function. I produced some
    simpler code in answer to an earlier responders comment that they couldnt
    follow the original.
    My actual function prototype is
    void MessageDlg(U8 nKeyMask, const U8 *pszTitle, const U8 **Items, U8
    numItems);
    Where nKeyMask is a mask of the key strokes accepted to close the dialog
    pszTitle is title of the dialog box
    Items is a pointer to an array/list of strings/char*
    numItems is the number of items in the array.

    Our records are large arrays of structs that are assigned permanent noinit
    space in battery backed ram. We have no heap or dynamic allocation.

    Please. Why is it not possible to pass the correct parameter directly rather
    than copying to another variable then passing that one?


    Claire
     
    Claire, Jun 25, 2003
    #3
  4. On Wed, 25 Jun 2003 16:48:16 +0100, in comp.lang.c , "Claire"
    <> wrote:

    >Re "dumb" comments. "You" will fully understand, as you are clearly an
    >expert at this, but do you know if "I" understand?


    this is a fair point. However its generally felt that in production
    code, comments ar there for *other people*, to explain to them what
    your code is doing. Comments should only exist for parts that are
    tricky.

    pointless comment:
    int foo; // declare variable foo of type int

    more useful comments
    FOO foo; //FOO is typdef'ed in header potato.h

    // must do integer maths here, to ensure x is rounded properly
    x = (int)y/456 + (intt)z/45;

    --
    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 =---
     
    Mark McIntyre, Jun 25, 2003
    #4
  5. Claire

    Chris Torek Guest

    (I wound up snipping all the code. Sorry about that.)

    In article <bdcg1q$gm3$>
    Claire <> writes:
    >My actual function prototype is
    >void MessageDlg(U8 nKeyMask, const U8 *pszTitle, const U8 **Items, U8
    >numItems);
    >Where nKeyMask is a mask of the key strokes accepted to close the dialog
    >pszTitle is title of the dialog box
    >Items is a pointer to an array/list of strings/char*
    >numItems is the number of items in the array.


    You are using "U8" instead of "char *" (e.g., for pszTitle), but
    compiler-generated strings have type "array of char". This forces
    you to use casts.

    Casts are bad news. If your code were to compile cleanly (no
    errors, no warnings, etc.) when cast-free, it would have a
    significantly higher chance of working. Of course, as I think you
    already found, simply changing "U8" to "char" does not make the
    code compile cleanly.

    The reason is that you have confused arrays, which can become
    pointer values under particular circumstances, with pointers.
    Although array objects do sometimes produce pointer values, array
    objects are not themselves pointers.

    >Please. Why is it not possible to pass the correct parameter directly rather
    >than copying to another variable then passing that one?


    See <http://67.40.109.61/torek/c/pa.html>. When you have an array
    named A of size N and element-type T, and pass &A to some other
    function, you get a pointer value of type "pointer to array N of
    T" that points to the entire array. If you pass "the value" of A,
    or use &A[0], you get a value of type "pointer to T" that points
    to the first element of the array A.

    >Our records are large arrays of structs that are assigned permanent noinit
    >space in battery backed ram. We have no heap or dynamic allocation.


    Such memory is usually a (relatively) scarce resource, so you might
    want to encode things tightly in this space, and expand them out for
    "regular" use in ordinary (non-backed-up) RAM. This sort of thing
    is probably more an issue for comp.arch.embedded, though.
    --
    In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://67.40.109.61/torek/index.html (for the moment)
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jun 26, 2003
    #5
  6. "Claire" <> wrote in message news:<bdc7cd$bl9$>...
    > void TestFunc(char **Str)
    > {
    > PlaceText(1,1,(char*)Str[0]);// 1st item in list of strings
    > PlaceText(2,1,(char*)Str[1]);// 2nd item in list of strings
    > }


    declare TestFunc as
    void TestFunc(char (*Str)[21])

    Then you can call this function as you would expect:
    TestFunc(pRecipe->pszStartStr);

    Of course the tests you wrote with s1_0, s2_00, etc. are no longer
    valid, because it is not the same a pointer to an array of 21 chars
    than another pointer to an array with a different size.

    Bernardo
     
    Bernardo Signori, Jun 26, 2003
    #6
    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. Jake
    Replies:
    0
    Views:
    593
  2. Johnny
    Replies:
    3
    Views:
    381
    Joona I Palaste
    Mar 7, 2004
  3. Zhidian Du
    Replies:
    0
    Views:
    174
    Zhidian Du
    Feb 21, 2004
  4. Tim Chase
    Replies:
    0
    Views:
    87
    Tim Chase
    Feb 16, 2014
  5. Terry Reedy
    Replies:
    0
    Views:
    97
    Terry Reedy
    Feb 16, 2014
Loading...

Share This Page