Help the helpless.. code read

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mark Richards

    Help the helpless.. code read

    I've been programming for many years, but have only recently taken a
    deep "C" dive (bad pun, i know) and need a lot of explanation from an
    expert. My questions center around those mysterious pointer beasties.

    The following code is excerpted from digitemp, a program that reads
    1-wire devices. Digitemp is the work of Brian C. Lane.

    As I walk through this code, I have a number of questions. I'm hoping
    someone with experience in pointers can provide a few for me (another
    pun) :) Also, I am sorry that this message is long. I tried to
    shorten it, but could not get my questions across any other way.

    I have indented the code and my questions and comments are preceded by
    // so they will be easier to follow. I hope this is less confusing and
    respectful of everyone's time.


    // The following _roms structure contains a list of 8 byte addresses...

    struct _roms
    {
    unsigned char *roms; /* Array of 8 bytes */
    int max; /* Maximum number */
    };

    // A variable, sensor_list is initialized...

    struct _roms *sensor_list

    // The roms part of the structure is filled with an "array" of sorts,
    // containing one or more 8-byte addresses. These addresses resolve,
    // when printed, as hex values.

    // For example: "12BAA91C000000 A3" is a valid address string.

    // The other variable within the _roms structure is "max" which is
    // loaded with the total number of addresses stored in "roms".

    // As I understand it, *sensor_list as defined above is a pointer to the
    // beginning of the entire structure defined as _roms.

    // Is this correct?


    // Let's say sensor_list is loaded with one 8-byte-wide address:
    // "12BAA91C000000 A3".

    // Here is how it's passed through in the code:

    read_all(&senso r_list);

    // Above, read_all(&senso r_list) says "call the read_all function and
    // pass as a parameter the (starting) address where the variable
    // sensor_list is. Is this a correct reading?

    int read_all(struct _roms *sensor_list)
    {
    int x;
    for(x = 0; x < (num_cs + sensor_list->max); x++)
    {
    read_device(sen sor_list, x);
    }
    return 0;
    }

    // It appears that a de-referenced pointer to sensor_list is being
    // defined in the function header, correct? (Since the address of
    // sensor_list was passed in the call to read_all(&senso r_list).)

    // From this, is it correct to assume that further de-referencing of
    // sensor_list will not be needed?

    // Here's where the action takes place:

    int read_device(str uct _roms *sensor_list, int sensor)
    {
    ...
    }

    // What seems odd to me is that, again, sensor_list is being defined in
    // this function header as a dereferenced pointer. Yet, the calling
    // function used a variable (sensor_list) that had already been
    // de-referenced. That's why it called read_device with just
    // "sensor_lis t", correct?

    // So there is a fundamental here that I am not understanding.

    // Within read_device, the sensor_list structure is used to pass a
    // complete 8-byte address to a function called owSerialNum:

    owSerialNum( 0, &sensor_list->roms[sensor*8], FALSE );

    // If I call the function like this:

    owSerialNum( 0, "12BAA91C000000 A3", FALSE );

    // it works perfectly. The documentation for owSerialNum says that the
    // second parameter is a buffer containing the address.

    // I can see that &sensor_list->roms[sensor*8] is saying, "the address
    // of roms[beginning at this offset] within a structure we call
    // "sensor_lis t".

    // Since the second parameter in
    // owSerialNum( 0,"12BAA91C0000 00A3",FALSE); is passed through as the
    // starting address of a buffer, and since &sensor_list->roms[sensor*8]
    // is also the address of a buffer, they must be synonymous, correct?

    // Well, they appear not to be so.
    // The following code works:

    printf(" Address: %s","12BAA91C00 0000A3");

    // This prints garbage:

    printf(" Address: %s",&sensor_lis t->roms[sensor*8] );

    // In fact, it looks like it's printing a memory address instead of the
    // contents of that address. Why?

    // If I do this...

    printf("Sensor here: %s\n",sensor_li st->roms[sensor*8]);

    // I get a segmentation fault (crash).
    // If I do this:

    printf("Sensor here: %s\n",*sensor_l ist->roms[sensor*8]);

    // The compiler complains: invalid type argument of `unary *'


    *********

    What I eventually want to do is pass into the application an address as
    a string parameter, and be able to pass it into the read_device
    function so that it is properly passed to owSerialNum(). It seems
    simple enough, but I'm hung up on the above issues at the moment. If I
    can be guided through the mud, this once, I think I'll have it.


    Help!

  • CBFalconer

    #2
    Re: Help the helpless.. code read

    Mark Richards wrote:[color=blue]
    >[/color]
    .... snip ...[color=blue]
    >
    > I have indented the code and my questions and comments are
    > preceded by // so they will be easier to follow. I hope this is
    > less confusing and respectful of everyone's time.
    >
    > // The following _roms structure contains a list of 8 byte
    > addresses...
    >
    > struct _roms
    > {
    > unsigned char *roms; /* Array of 8 bytes */
    > int max; /* Maximum number */
    > };[/color]

    Let's stop right there, as the rest of the assumptions will be
    wrong. roms is a pointer to an unsigned char. It is not an array
    of any sort. I read no further.

    In addition the identifier '_roms' is reserved for the
    implementation. You should not be using it. Such use may cause
    undefined behaviour.

    --
    A: Because it fouls the order in which people normally read text.
    Q: Why is top-posting such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?


    Comment

    • Allin Cottrell

      #3
      Re: Help the helpless.. code read

      Mark Richards wrote:[color=blue]
      > I've been programming for many years, but have only recently taken a
      > deep "C" dive (bad pun, i know) and need a lot of explanation from an
      > expert. My questions center around those mysterious pointer beasties.[/color]

      I'll tackle a small portion of your question.
      [color=blue]
      > // The following _roms structure contains a list of 8 byte addresses...
      >
      > struct _roms
      > {
      > unsigned char *roms; /* Array of 8 bytes */
      > int max; /* Maximum number */
      > };
      >
      > // A variable, sensor_list is initialized...
      >
      > struct _roms *sensor_list[/color]

      Registered. Although this line is not valid C as it stands. It
      needs a semi-colon as termination, possibly preceded by an
      actual initialization.
      [color=blue]
      > // As I understand it, *sensor_list as defined above is a pointer to the
      > // beginning of the entire structure defined as _roms.[/color]

      Not quite: sensor_list is declared as having the type, "pointer to
      struct _roms". "*sensor_li st", that is the thing you get when you
      dereference sensor_list, then has type struct _roms.
      [color=blue]
      > // Here is how it's passed through in the code:
      >
      > read_all(&senso r_list);[/color]
      [color=blue]
      >
      > // Above, read_all(&senso r_list) says "call the read_all function and
      > // pass as a parameter the (starting) address where the variable
      > // sensor_list is. Is this a correct reading?[/color]

      Yes, it's correct.
      [color=blue]
      > int read_all(struct _roms *sensor_list)[/color]

      Stop right there. Unless there's some slippage in your quotation
      from the original C source, this is an error. "sensor_lis t" was
      of type "pointer to struct _roms". The thing you get by writing
      "&sensor_li st" is then of type "pointer to pointer to struct _roms",
      or struct _roms **. And this is not compatible with the stated
      parameter type for read_all().

      Allin Cottrell
      Wake Forest University

      Comment

      • Mark Richards

        #4
        Re: Help the helpless.. code read

        > In addition the identifier '_roms' is reserved for the[color=blue]
        > implementation. You should not be using it. Such use may cause
        > undefined behaviour.[/color]

        When you say it's reserved for the implementation, do you mean that it's
        possibly a reserved word, or that the underscore should not be used?
        [color=blue][color=green]
        >>roms is a pointer to an unsigned char.[/color][/color]
        If I define:

        struct _roms *sensor_list

        then the variable sensor_list acts as a pointer to the structure, correct?




        CBFalconer wrote:[color=blue]
        > Mark Richards wrote:
        >
        > ... snip ...
        >[color=green]
        >>I have indented the code and my questions and comments are
        >>preceded by // so they will be easier to follow. I hope this is
        >>less confusing and respectful of everyone's time.
        >>
        >>// The following _roms structure contains a list of 8 byte
        >> addresses...
        >>
        >> struct _roms
        >> {
        >> unsigned char *roms; /* Array of 8 bytes */
        >> int max; /* Maximum number */
        >> };[/color]
        >
        >
        > Let's stop right there, as the rest of the assumptions will be
        > wrong. roms is a pointer to an unsigned char. It is not an array
        > of any sort. I read no further.
        >
        >[/color]

        Comment

        • Chris Dollin

          #5
          Re: Help the helpless.. code read

          Mark Richards wrote:
          [color=blue][color=green]
          > > In addition the identifier '_roms' is reserved for the
          > > implementation. You should not be using it. Such use may cause
          > > undefined behaviour.[/color]
          >
          > When you say it's reserved for the implementation, do you mean that it's
          > possibly a reserved word, or that the underscore should not be used?[/color]

          Sufficiently many identifier-like things beginning with _ are reserved
          to the implementation that the easiest rule to remember is "don't use
          them".

          The implementation is free to attach any meaning it pleases to such
          words. (I can't remember whether it's obliged to document those
          meanings.) In particular it may use them as struct tags for its own
          structures such as might be hidden in #include files.
          [color=blue][color=green][color=darkred]
          > >>roms is a pointer to an unsigned char.[/color][/color]
          > If I define:
          >
          > struct _roms *sensor_list
          >
          > then the variable sensor_list acts as a pointer to the structure, correct?[/color]

          The variable sensor_list, when its value is required, should either be
          the null pointer or point to an object of type struct _roms (which may be
          the first of several such contiguous objects, of course).

          --
          Chris "electric hedgehog" Dollin
          C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
          C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html

          Comment

          • Mark Richards

            #6
            Re: Help the helpless.. code read

            Allin,
            [color=blue]
            > Stop right there. Unless there's some slippage in your quotation
            > from the original C source, this is an error. "sensor_lis t" was
            > of type "pointer to struct _roms". The thing you get by writing
            > "&sensor_li st" is then of type "pointer to pointer to struct _roms",
            > or struct _roms **. And this is not compatible with the stated
            > parameter type for read_all().[/color]

            Here's how it's initialized (I've removed extraneous code):

            int main(int argc, char *argv[])
            {
            ...
            struct _roms sensor_list; /* Attached Roms */
            ...

            if(read_rcfile( conf_file, &sensor_list ) < 0);
            ...
            // later on in main():

            read_all(&senso r_list);




            int read_rcfile(cha r *fname, struct _roms *sensor_list)
            ...
            sensor_list->roms = malloc(sensors * 8);
            sensor_list->max = sensors;

            for(x = 0; x < 8; x++)
            {
            ptr = strtok(NULL, " \t\n");
            sensor_list->roms[(sensors * 8) + x] = strtol(ptr, (char **) NULL, 0);
            }

            -------------------

            Indeed, the call read_all(&senso r_list); is being made.

            So...

            This:
            struct _roms sensor_list; /* Attached Roms */

            initializes the variable sensor_list which, when referenced, is a
            pointer to the start of the structure...

            and this:
            if(read_rcfile( conf_file, &sensor_list ) < 0);

            passes that pointer (of sensor_list) to read_rcfile. If instead it read
            sensor_list, then the variable would be passed by value, correct?

            and this:

            int read_rcfile(cha r *fname, struct _roms *sensor_list)

            says that the incoming variable *sensor_list is the address of the
            variable sensor_list?

            and this:

            read_all(&senso r_list);

            says to pass the address of sensor_list (not a pointer address) to read_all?



            I'm trying to follow the state of sensor_list from initialization. Here
            are my assumptions:


            struct _roms sensor_list; -> a block of memory defined by the
            width of _roms is allocated and
            sensor_list is assigned to reference
            it;

            if(read_rcfile( conf_file, &sensor_list ) < 0);
            -> the address of sensor_list is passed
            into read_rcfile. Oops. I thought
            sensor_list was the address;

            int read_rcfile(cha r *fname, struct _roms *sensor_list);
            -> sensor_list is now a pointer to the
            new structure;

            sensor_list->roms
            -> the use of sensor_list is now
            assumed to be a pointer, since the
            function typedef was *sensor_list.
            I assume that referencing it like
            this would be illegal:

            struct _roms sensor_list;
            sensor_list->roms (...

            It must be done thusly?
            *sensor_list->roms (...

            Now, back in main():

            read_all(&senso r_list);
            -> So the address of the address is
            being stated here? That does seem
            strange. However, this is the
            original unmodified code, that works.



            As my wife is loathe to say, I'm clearly missing a fundamental here.


            -m-






            Allin Cottrell wrote:
            [color=blue]
            > Mark Richards wrote:
            >[color=green]
            >> I've been programming for many years, but have only recently taken a
            >> deep "C" dive (bad pun, i know) and need a lot of explanation from an
            >> expert. My questions center around those mysterious pointer beasties.[/color]
            >
            >
            > I'll tackle a small portion of your question.
            >[color=green]
            >> // The following _roms structure contains a list of 8 byte addresses...
            >>
            >> struct _roms
            >> {
            >> unsigned char *roms; /* Array of 8 bytes */
            >> int max; /* Maximum number */
            >> };
            >>
            >> // A variable, sensor_list is initialized...
            >>
            >> struct _roms *sensor_list[/color]
            >
            >
            > Registered. Although this line is not valid C as it stands. It
            > needs a semi-colon as termination, possibly preceded by an
            > actual initialization.
            >[color=green]
            >> // As I understand it, *sensor_list as defined above is a pointer to the
            >> // beginning of the entire structure defined as _roms.[/color]
            >
            >
            > Not quite: sensor_list is declared as having the type, "pointer to
            > struct _roms". "*sensor_li st", that is the thing you get when you
            > dereference sensor_list, then has type struct _roms.
            >[color=green]
            >> // Here is how it's passed through in the code:
            >>
            >> read_all(&senso r_list);[/color]
            >
            >[color=green]
            >>
            >> // Above, read_all(&senso r_list) says "call the read_all function and
            >> // pass as a parameter the (starting) address where the variable
            >> // sensor_list is. Is this a correct reading?[/color]
            >
            >
            > Yes, it's correct.
            >[color=green]
            >> int read_all(struct _roms *sensor_list)[/color]
            >
            >
            > Stop right there. Unless there's some slippage in your quotation
            > from the original C source, this is an error. "sensor_lis t" was
            > of type "pointer to struct _roms". The thing you get by writing
            > "&sensor_li st" is then of type "pointer to pointer to struct _roms",
            > or struct _roms **. And this is not compatible with the stated
            > parameter type for read_all().
            >
            > Allin Cottrell
            > Wake Forest University[/color]

            Comment

            • CBFalconer

              #7
              Re: Help the helpless.. code read

              Mark Richards wrote:[color=blue]
              >[color=green]
              >> In addition the identifier '_roms' is reserved for the
              >> implementation. You should not be using it. Such use may cause
              >> undefined behaviour.[/color]
              >
              > When you say it's reserved for the implementation, do you mean
              > that it's possibly a reserved word, or that the underscore should
              > not be used?[/color]

              Please do not toppost. Please do snip non-germane quoted portions.

              It is not a reserved word - those are completely specified in the
              standard. However the implementation may use identifiers with
              leading underscores freely, and is quite likely to do so in the
              system headers. The way to avoid clashes is to avoid using such
              identifiers.

              --
              A: Because it fouls the order in which people normally read text.
              Q: Why is top-posting such a bad thing?
              A: Top-posting.
              Q: What is the most annoying thing on usenet and in e-mail?


              Comment

              • Mark Richards

                #8
                Re: Help the helpless.. code read

                > Please do not toppost. Please do snip non-germane quoted portions.
                Sorry. Will do.
                [color=blue]
                > The way to avoid clashes is to avoid using such
                > identifiers.[/color]
                Thanks for the clarification.

                -m-

                Comment

                • Allin Cottrell

                  #9
                  Re: Help the helpless.. code read

                  Mark Richards wrote:[color=blue]
                  > Allin,
                  >[color=green]
                  > > Stop right there. Unless there's some slippage in your quotation
                  > > from the original C source, this is an error. "sensor_lis t" was
                  > > of type "pointer to struct _roms". The thing you get by writing
                  > > "&sensor_li st" is then of type "pointer to pointer to struct _roms",
                  > > or struct _roms **. And this is not compatible with the stated
                  > > parameter type for read_all().[/color]
                  >
                  > Here's how it's initialized (I've removed extraneous code):
                  >
                  > int main(int argc, char *argv[])
                  > {
                  > ...
                  > struct _roms sensor_list; /* Attached Roms */[/color]

                  Ah, we're OK then: "sensor_lis t" is an actual instance of struct
                  _roms, not a pointer to same. So when you take the address:

                  &sensor_list

                  you get something of type "struct _roms *", or pointer-to-struct-
                  _roms, which is an acceptable parameter to the function read_all(),
                  cited earlier.
                  [color=blue]
                  > So...
                  >
                  > This:
                  > struct _roms sensor_list; /* Attached Roms */
                  >
                  > initializes the variable sensor_list which, when referenced, is a
                  > pointer to the start of the structure...[/color]

                  ....which, when one takes its address, yields a pointer to the
                  structure ("start of" is kinda redundant).
                  [color=blue]
                  > and this:
                  > if(read_rcfile( conf_file, &sensor_list ) < 0);
                  >
                  > passes that pointer (of sensor_list) to read_rcfile. If instead it read
                  > sensor_list, then the variable would be passed by value, correct?[/color]

                  The function read_rcfile() would in that case get a "local copy" of
                  the structure, and the struct in the caller would remain unmodified,
                  contrary to the programmer's intention, Yes.
                  [color=blue]
                  > and this:
                  >
                  > int read_rcfile(cha r *fname, struct _roms *sensor_list)
                  >
                  > says that the incoming variable *sensor_list is the address of the
                  > variable sensor_list?[/color]

                  Yup.
                  [color=blue]
                  > and this:
                  >
                  > read_all(&senso r_list);
                  >
                  > says to pass the address of sensor_list (not a pointer address) to
                  > read_all?[/color]

                  The address of a struct (and hence a pointer-to-struct), but not the
                  address of a pointer, no.
                  [color=blue]
                  > I'm trying to follow the state of sensor_list from initialization. Here
                  > are my assumptions:
                  >
                  > struct _roms sensor_list; -> a block of memory defined by the
                  > width of _roms is allocated and
                  > sensor_list is assigned to reference
                  > it;[/color]

                  Yes.[color=blue]
                  >
                  > if(read_rcfile( conf_file, &sensor_list ) < 0);
                  > -> the address of sensor_list is passed
                  > into read_rcfile. Oops. I thought
                  > sensor_list was the address;[/color]

                  Your current thought is correct.[color=blue]
                  >
                  > int read_rcfile(cha r *fname, struct _roms *sensor_list);
                  > -> sensor_list is now a pointer to the
                  > new structure;[/color]

                  Within the function read_rcfile(), sensor_list figures as
                  a pointer-to-struct, not a struct "in person", yes.
                  [color=blue]
                  > sensor_list->roms
                  > -> the use of sensor_list is now
                  > assumed to be a pointer, since the
                  > function typedef was *sensor_list.[/color]

                  "typedef" is not the term you want here. The parameter was
                  declared to be of type "pointer to struct _roms".
                  [color=blue]
                  > I assume that referencing it like
                  > this would be illegal:
                  >
                  > struct _roms sensor_list;
                  > sensor_list->roms (...[/color]

                  Yes, if the parameter to the function were of type struct _roms,
                  you would get a compiler error on using the syntax

                  sensor_list->roms ...
                  [color=blue]
                  > It must be done thusly?
                  > *sensor_list->roms (...[/color]

                  Huh? If the parameter (counter-factually) had been,
                  struct _roms sensor_list, then you'd do things like

                  sensor_list.rom s = ...

                  (In your example, the prepended "*" doesn't make the invalid
                  "->" any less invalid.)
                  [color=blue]
                  > Now, back in main():
                  >
                  > read_all(&senso r_list);
                  > -> So the address of the address is
                  > being stated here?[/color]

                  No, I fear you have lost the place. Up above, you had "sensor_lis t"
                  as of type plain "struct _roms" in main.

                  Allin Cottrell
                  Wake Forest University

                  Comment

                  • Nick Keighley

                    #10
                    Re: Help the helpless.. code read

                    Mark Richards <nospam@massmic ro.com> wrote in message news:<40cfa921$ 0$96448$9a6e19e a@news.newshost ing.com>...

                    <snip>
                    [color=blue]
                    > [...]My questions center around those mysterious pointer beasties.[/color]

                    find a good book. "The C Programming Language" by Kernighan and Richie
                    explains pointers quite well.

                    <snip>
                    [color=blue]
                    > // The following _roms structure contains a list of 8 byte addresses...[/color]

                    as others have noted, no it doesn't.


                    [color=blue]
                    >
                    > struct _roms
                    > {
                    > unsigned char *roms; /* Array of 8 bytes */
                    > int max; /* Maximum number */
                    > };
                    >
                    > // A variable, sensor_list is initialized...
                    >
                    > struct _roms *sensor_list[/color]

                    else-thread you change this to

                    struct _roms sensor_list;

                    <snip>
                    [color=blue]
                    > read_all(&senso r_list);
                    >
                    > // Above, read_all(&senso r_list) says "call the read_all function and
                    > // pass as a parameter the (starting) address where the variable
                    > // sensor_list is. Is this a correct reading?[/color]

                    call the read_all function with a pointer to the sensor_list struct.
                    If you like you use "address" instead of "pointer". On a typical
                    implementation pointers will be addresses.

                    [color=blue]
                    > int read_all(struct _roms *sensor_list)
                    > {
                    > int x;
                    > for(x = 0; x < (num_cs + sensor_list->max); x++)
                    > {
                    > read_device(sen sor_list, x);
                    > }
                    > return 0;
                    > }
                    >
                    > // It appears that a de-referenced pointer to sensor_list is being
                    > // defined in the function header, correct?[/color]

                    no. sensor_list is a pointer to struct _roms. This is the source of
                    confusion to beginning C programmers. * is used in two different ways
                    (well three if you count multiplication) .

                    int *a;

                    a is ptr to int

                    *a = 1;

                    a is being dereferenced. a is still a pointer to int but *a is an int.
                    Another way of looking at it that

                    int *a;

                    declares *a to be an int. Usage mirrors declaration syntax. Opinions vary
                    as to whether this was a good idea.

                    <snip>
                    [color=blue]
                    > // Within read_device, the sensor_list structure is used to pass a
                    > // complete 8-byte address to a function called owSerialNum:
                    >
                    > owSerialNum( 0, &sensor_list->roms[sensor*8], FALSE );[/color]

                    why did you multiply by 8?
                    why did you take the address?
                    Try:-

                    owSerialNum (0, sensor_list->roms [sensor], FALSE;

                    (assuming you've initialised roms correctly)
                    [color=blue]
                    > // If I call the function like this:
                    >
                    > owSerialNum( 0, "12BAA91C000000 A3", FALSE );
                    >
                    > // it works perfectly. The documentation for owSerialNum says that the
                    > // second parameter is a buffer containing the address.
                    >
                    > // I can see that &sensor_list->roms[sensor*8] is saying, "the address
                    > // of roms[beginning at this offset] within a structure we call
                    > // "sensor_lis t".[/color]

                    yes, but roms is a pointer to unsigned char, why take its address?

                    [color=blue]
                    > // Since the second parameter in
                    > // owSerialNum( 0,"12BAA91C0000 00A3",FALSE); is passed through as the
                    > // starting address of a buffer, and since &sensor_list->roms[sensor*8]
                    > // is also the address of a buffer, they must be synonymous, correct?[/color]

                    nope.

                    <snip>


                    --
                    Nick Keighley

                    You are in a clearing. You can see a spire in the distance.
                    You can also see a copy of "C Unleashed".
                    : INV
                    You have;
                    a DeathStation 900 laptop,
                    a voucher for a free pizza,
                    and a torch.
                    : TAKE BOOK
                    You can't. It's too heavy.
                    Bill Godfrey (clc)

                    Comment

                    • Mark Richards

                      #11
                      Re: Help the helpless.. code read

                      Nick,

                      Thanks for your book suggestion. I have it, and have read the pointers
                      and arrays chapter once more. Something, however, isn't sinking in (yet).

                      I think there was some confusion in my use of the term "address".

                      In the structure:

                      struct _roms
                      {
                      unsigned char *roms; /* Array of 8 bytes */
                      int max; /* Maximum number */
                      };

                      *roms provides storage for a "8-byte 1-wire device address". This
                      memory location is supposed to store a string similar to
                      "12BAA91C000000 A3". I should have been very specific with my use of
                      this term.

                      I've read carefully what you conveyed. I cannot understand the
                      effective difference between:

                      owSerialNum( 0, "12BAA91C000000 A3", FALSE );

                      and
                      int sensor = 0;
                      owSerialNum( 0, &sensor_list->roms[sensor*8], FALSE );


                      owSerialNum( 0, "12BAA91C000000 A3", FALSE ); and owSerialNum( 0,
                      &sensor_list->roms[sensor*8], FALSE ); both work properly, but if I:

                      unsigned char TempSN[16];
                      strcpy(TempSN," 12BAA91C000000A 3");
                      printf("Rom address: %s",TempSN);

                      I get: "Rom address: 12BAA91C000000A 3"

                      If I do this:

                      sensor = 0;
                      strcpy(TempSN,& sensor_list.rom s[sensor*8]);
                      printf("Rom address: %s",TempSN);

                      I get: "Rom address: ;X" (garbage). In the above, I don't quite see why
                      &sensor_list.ro ms[sensor*8] doesn't return a string since the
                      dereference operator is used.


                      If I take your suggestion and remove the address of operator (&):

                      owSerialNum (0, sensor_list->roms [sensor], FALSE);

                      I get a compiler warning: passing arg 2 of `owSerialNum' makes pointer
                      from integer without a cast.


                      [color=blue][color=green]
                      >>struct _roms *sensor_list[/color]
                      >else-thread you change this to
                      >
                      > struct _roms sensor_list;[/color]

                      I was not being specific enough here, too.

                      In main() it's defined thusly:
                      struct _roms sensor_list; /* Attached Roms */

                      It's passed in a function call like this:

                      int read_all(struct _roms *sensor_list)

                      And within the function that it is passed as a parameter, it's used like
                      this:

                      read_all(&senso r_list);



                      So, based on your explanation, is it correct to say:

                      struct _roms sensor_list;

                      defines the variable sensor_list which is yet to be initialized;

                      int read_all(struct _roms *sensor_list)

                      received a pointer (the address of) sensor_list;

                      and
                      read_all(&senso r_list);

                      passes the value found at sensor_list's address?


                      .....


                      As I continued to puzzle at sensor_list, I tried the following code:

                      struct _roms sensor_list;
                      struct _roms *new_sensor_lis t;
                      unsigned char *theaddress;

                      /* Make sure the structure is erased */
                      bzero(&sensor_l ist, sizeof(struct _roms));

                      // sensor_list.rom s is NULL now.

                      // this initializes sensor_list
                      read_rcfile(con f_file, &sensor_list );
                      // sensor_list.rom s is NOT NULL now.

                      // initialize pointer
                      new_sensor_list = &sensor_list ;
                      theaddress = &new_sensor_lis t->roms[0];

                      printf("Rom address: %s",theaddress) ;

                      This outputs garbage.

                      Comment

                      • Allin Cottrell

                        #12
                        Re: Help the helpless.. code read

                        Mark Richards wrote:
                        [color=blue]
                        > If I do this:
                        >
                        > sensor = 0;
                        > strcpy(TempSN,& sensor_list.rom s[sensor*8]);
                        > printf("Rom address: %s",TempSN);
                        >
                        > I get: "Rom address: ;X" (garbage). In the above, I don't quite see why
                        > &sensor_list.ro ms[sensor*8] doesn't return a string since the
                        > dereference operator is used.[/color]

                        The character '*' does double duty in C: as the multiplication operator,
                        and for dereferencing a pointer. In well-formed code the specific
                        meaning is unambiguous in context. In the fragment above, since both
                        'sensor' and '8' represent integers, the '*' is unambiguously the
                        multiplication operator: sensor*8 = 0*8 = 0.

                        Allin Cottrell

                        Comment

                        • CBFalconer

                          #13
                          Re: Help the helpless.. code read

                          Mark Richards wrote:[color=blue]
                          >
                          > Thanks for your book suggestion. I have it, and have read the
                          > pointers and arrays chapter once more. Something, however, isn't
                          > sinking in (yet).
                          >
                          > I think there was some confusion in my use of the term "address".
                          >
                          > In the structure:
                          >
                          > struct _roms
                          > {
                          > unsigned char *roms; /* Array of 8 bytes */
                          > int max; /* Maximum number */
                          > };
                          >
                          > *roms provides storage for a "8-byte 1-wire device address".
                          > This memory location is supposed to store a string similar to
                          > "12BAA91C000000 A3". I should have been very specific with my
                          > use of this term.[/color]

                          As you have been told before, no it doesn't. The comment is
                          WRONG. roms provides space for a pointer to char, and is
                          uninitialized.

                          Why ask for advice if you simply ignore it?

                          --
                          fix (vb.): 1. to paper over, obscure, hide from public view; 2.
                          to work around, in a way that produces unintended consequences
                          that are worse than the original problem. Usage: "Windows ME
                          fixes many of the shortcomings of Windows 98 SE". - Hutchison

                          Comment

                          • Barry Schwarz

                            #14
                            Re: Help the helpless.. code read

                            On Thu, 17 Jun 2004 15:01:33 -0400, Mark Richards
                            <nospam@massmic ro.com> wrote:
                            [color=blue]
                            >Nick,
                            >
                            >Thanks for your book suggestion. I have it, and have read the pointers
                            >and arrays chapter once more. Something, however, isn't sinking in (yet).
                            >
                            >I think there was some confusion in my use of the term "address".
                            >
                            >In the structure:
                            >
                            > struct _roms
                            > {
                            > unsigned char *roms; /* Array of 8 bytes */
                            > int max; /* Maximum number */
                            > };
                            >
                            >*roms provides storage for a "8-byte 1-wire device address". This
                            >memory location is supposed to store a string similar to
                            >"12BAA91C00000 0A3". I should have been very specific with my use of
                            >this term.[/color]

                            You are having trouble with both terminology and notation.

                            Until you initialize it with some valid address, roms does not provide
                            anything other than the potential to be initialized.

                            Once roms is initialized and once the area it points is initialized,
                            *roms is always exactly the value of the first character (or byte if
                            you prefer) in that area.

                            You say it is the address of an 8 byte area but then you give an
                            example of a 17 byte string. Did you perhaps mean the 8 hex values
                            0x12, 0xba, 0xa9, ...?
                            [color=blue]
                            >
                            >I've read carefully what you conveyed. I cannot understand the
                            >effective difference between:
                            >
                            > owSerialNum( 0, "12BAA91C000000 A3", FALSE );
                            >
                            >and
                            > int sensor = 0;
                            > owSerialNum( 0, &sensor_list->roms[sensor*8], FALSE );[/color]

                            If roms is not initialized, the second invokes undefined behavior. If
                            roms is initialized to point to an 8-byte area as you suggest, then
                            the two cannot be equivalent since

                            The first passes a string of length 16 and each character (except
                            the 17th which is '\0') is printable.

                            The second passes an array of only 8 characters (per your comment)
                            which are most likely unprintable and probably not nul terminated.
                            [color=blue]
                            >
                            >
                            >owSerialNum( 0, "12BAA91C000000 A3", FALSE ); and owSerialNum( 0,
                            >&sensor_list->roms[sensor*8], FALSE ); both work properly, but if I:
                            >
                            > unsigned char TempSN[16];
                            > strcpy(TempSN," 12BAA91C000000A 3");[/color]

                            This invokes undefined behavior since strcpy will attempt to copy the
                            '\0' and there is no room in TempSN for it.
                            [color=blue]
                            > printf("Rom address: %s",TempSN);
                            >
                            >I get: "Rom address: 12BAA91C000000A 3"
                            >
                            >If I do this:
                            >
                            > sensor = 0;
                            > strcpy(TempSN,& sensor_list.rom s[sensor*8]);
                            > printf("Rom address: %s",TempSN);
                            >
                            >I get: "Rom address: ;X" (garbage). In the above, I don't quite see why
                            >&sensor_list.r oms[sensor*8] doesn't return a string since the[/color]

                            You need to show how roms is initialized and how the area it points to
                            is initialized.
                            [color=blue]
                            >dereference operator is used.
                            >
                            >
                            >If I take your suggestion and remove the address of operator (&):
                            >
                            > owSerialNum (0, sensor_list->roms [sensor], FALSE);
                            >
                            >I get a compiler warning: passing arg 2 of `owSerialNum' makes pointer
                            >from integer without a cast.[/color]

                            As well you should. If you remove the &, you should also remove the
                            [sensor].
                            [color=blue]
                            >
                            >
                            >[color=green][color=darkred]
                            > >>struct _roms *sensor_list[/color]
                            > >else-thread you change this to
                            > >
                            > > struct _roms sensor_list;[/color]
                            >
                            >I was not being specific enough here, too.
                            >
                            >In main() it's defined thusly:
                            > struct _roms sensor_list; /* Attached Roms */
                            >
                            >It's passed in a function call like this:
                            >
                            > int read_all(struct _roms *sensor_list)
                            >
                            >And within the function that it is passed as a parameter, it's used like
                            >this:
                            >
                            > read_all(&senso r_list);
                            >
                            >
                            >
                            >So, based on your explanation, is it correct to say:
                            >
                            > struct _roms sensor_list;
                            >
                            >defines the variable sensor_list which is yet to be initialized;[/color]

                            Yes
                            [color=blue]
                            >
                            > int read_all(struct _roms *sensor_list)
                            >
                            >received a pointer (the address of) sensor_list;[/color]

                            Yes
                            [color=blue]
                            >
                            >and
                            > read_all(&senso r_list);
                            >
                            >passes the value found at sensor_list's address?[/color]

                            No. It passes the address itself. It cares not a whit for any value
                            or missing value at that address.
                            [color=blue]
                            >
                            >
                            >....
                            >
                            >
                            >As I continued to puzzle at sensor_list, I tried the following code:
                            >
                            > struct _roms sensor_list;
                            > struct _roms *new_sensor_lis t;
                            > unsigned char *theaddress;
                            >
                            > /* Make sure the structure is erased */
                            > bzero(&sensor_l ist, sizeof(struct _roms));
                            >
                            > // sensor_list.rom s is NULL now.[/color]

                            No, sensor_list.rom s is now all bits 0 and you have no idea what that
                            value means in a char*.
                            [color=blue]
                            >
                            > // this initializes sensor_list
                            > read_rcfile(con f_file, &sensor_list );
                            > // sensor_list.rom s is NOT NULL now.
                            >
                            > // initialize pointer
                            > new_sensor_list = &sensor_list ;
                            > theaddress = &new_sensor_lis t->roms[0];
                            >
                            > printf("Rom address: %s",theaddress) ;[/color]

                            While is may be true that roms is not NULL after the return from
                            read_rcfile, how was the area it points to initialized? In
                            particular, was it initialized with a printable nul-terminated string?
                            [color=blue]
                            >
                            >This outputs garbage.[/color]

                            You need to post some compilable code that demonstrates the problem.


                            <<Remove the del for email>>

                            Comment

                            • tristan

                              #15
                              Re: Help the helpless.. code read

                              Allin Cottrell wrote:[color=blue]
                              > Mark Richards wrote:[color=green]
                              > > Here's how it's initialized (I've removed extraneous code):
                              > >
                              > > int main(int argc, char *argv[])
                              > > {
                              > > ...
                              > > struct _roms sensor_list; /* Attached Roms */[/color][/color]

                              [big snip]
                              [color=blue][color=green]
                              > > and this:
                              > >
                              > > int read_rcfile(cha r *fname, struct _roms *sensor_list)
                              > >
                              > > says that the incoming variable *sensor_list is the address of the
                              > > variable sensor_list?[/color]
                              >
                              > Yup.[/color]

                              Maybe. Note that, syntactically speaking, the thing named sensor_list
                              in this function bears no relation whatsoever to the thing in main()
                              named sensor_list. read_rcfile() knows only that it has a local
                              variable called sensor_list, which is a pointer to a struct _roms.
                              [color=blue][color=green]
                              > > and this:
                              > >
                              > > read_all(&senso r_list);
                              > >
                              > > says to pass the address of sensor_list (not a pointer address) to
                              > > read_all?[/color]
                              >
                              > The address of a struct (and hence a pointer-to-struct), but not the
                              > address of a pointer, no.
                              >[color=green]
                              > > I'm trying to follow the state of sensor_list from initialization. Here
                              > > are my assumptions:
                              > >
                              > > struct _roms sensor_list; -> a block of memory defined by the
                              > > width of _roms is allocated and
                              > > sensor_list is assigned to reference
                              > > it;[/color]
                              >
                              > Yes.[/color]

                              You now have a local variable of type struct _roms, which is known
                              by the name sensor_list. It isn't allocated in the sense of
                              dynamic allocation, nor is sensor_list a reference in the sense
                              that e.g. Java uses it.
                              [color=blue][color=green]
                              > > if(read_rcfile( conf_file, &sensor_list ) < 0);
                              > > -> the address of sensor_list is passed
                              > > into read_rcfile. Oops. I thought
                              > > sensor_list was the address;[/color]
                              >
                              > Your current thought is correct.[/color]

                              sensor_list is the variable itself.
                              [color=blue][color=green]
                              > > int read_rcfile(cha r *fname, struct _roms *sensor_list);
                              > > -> sensor_list is now a pointer to the
                              > > new structure;[/color]
                              >
                              > Within the function read_rcfile(), sensor_list figures as
                              > a pointer-to-struct, not a struct "in person", yes.[/color]

                              Which, apart from having an identical spelling, is completely
                              separate from the previously mentioned uses of sensor_list.
                              [color=blue][color=green]
                              > > sensor_list->roms
                              > > -> the use of sensor_list is now
                              > > assumed to be a pointer, since the
                              > > function typedef was *sensor_list.[/color]
                              >
                              > "typedef" is not the term you want here. The parameter was
                              > declared to be of type "pointer to struct _roms".[/color]

                              And there's no need to assume, it's all quite explicit :)

                              [small snip]
                              [color=blue][color=green]
                              > > Now, back in main():
                              > >
                              > > read_all(&senso r_list);
                              > > -> So the address of the address is
                              > > being stated here?[/color]
                              >
                              > No, I fear you have lost the place. Up above, you had "sensor_lis t"
                              > as of type plain "struct _roms" in main.[/color]

                              I don't think you mentioned what language(s) you had previously
                              programmed in. Be aware that in C, variables are always passed by
                              value, and names of variables are direct aliases for values. If you
                              want an address, you must be explicit. This includes variables of
                              struct types. This is in contrast to something like Java, where almost
                              all variables are actually indirect references, without you ever saying
                              so specifically.

                              HTH
                              Tristan

                              Comment

                              Working...