Arrays as function parameters and sizeof()

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andreas Eibach

    Arrays as function parameters and sizeof()

    Hi,

    when I had in mind to turn this code (which worked fine in main()) to a
    separate function, I stumbled upon this...(of course, it's way bigger than
    that, but I hope this short snippet can demonstrate the issue anyway)

    -begin code (Ì) -
    int main(void)
    {
    unsigned char rawdata[96] =
    {0x32, 0xA7, 0x53, 0x00, 0xE0, 0x20, 0x0F, 0x19,
    0x00, 0x00, 0x03, 0x70, 0x43, 0xFA, 0x00, 0x18,
    0x4E, 0xAE, 0xFF, 0xA0, 0x4A, 0x80, 0x67, 0x0A
    }; /* note, rest is _intended_ to be zeroes */

    unsigned long x = 0;
    int i;

    for(i=0; i < sizeof(rawdata)/(sizeof(unsigne d long)); i++)
    {
    ...
    x = ((rawdata[i*4+0] << 8) | .....;
    /* ... */
    }
    return 0;
    }
    -end code (I)-

    The for() line contains an i < sizeof(rawdata) . In main(), this causes no
    problems, however, if we (commonly) assume that the function-internal
    variables are completely different, we *may* run into trouble...


    -begin code (II)-
    unsigned long doMagic (unsigned char[]);

    int main(void)
    {
    unsigned char rawdata[64] = {
    0x32, 0xA7, 0x53, 0x00, 0xE0, 0x20, 0x0F, 0x19,
    0x00, 0x00, 0x03, 0x70, 0x43, 0xFA, 0x00, 0x18,
    0x4E, 0xAE, 0xFF, 0xA0, 0x4A, 0x80, 0x67, 0x0A
    }; /* note, rest is _intended_ to be zeroes */

    unsigned long x = doMagic(rawdata );
    ... /* e. g. printf output */
    return 0;
    }

    unsigned long doMagic (unsigned char arr[])
    {
    int i;
    for(i=0; i < sizeof(arr)/(sizeof(unsigne d long)); i++)
    {
    ...
    x = ((arr[i*4+0] << 8) | ....... ;
    }
    }
    -end code (II)


    For an absolute beginner, this looks "working fine", but it does not. :)
    sizeof(arr) is *NOT* the size of the array (just as I too thought before),
    but merely the size of the small pointer (here it was 4). This caused the
    for loop to get exited prematurely.

    The only way out with the portable solution was to write a different
    doMagic():

    unsigned long doMagic (unsigned char arr[], unsigned int len);

    and then *externally* enter the function using sizeof(rawdata) as length
    "info".
    This worked fine.

    But ... is there no other way to *compute* the actual size of the array
    (here 96) *inside* the function without expecting to have it "pre-chewed" by
    the calling routine?

    -Andreas

  • Eric Sosman

    #2
    Re: Arrays as function parameters and sizeof()

    Andreas Eibach wrote:
    [... sizeof function parameter declared as array ...]
    But ... is there no other way to *compute* the actual size of the array
    (here 96) *inside* the function without expecting to have it "pre-chewed" by
    the calling routine?
    No. Although you can write the parameter as if it were an
    array, in truth it is a pointer to an element of the array. So
    sizeof produces the size of a pointer, not the size of the thing
    pointed to nor the size of the whole array of things.

    See Question 6.21 -- in fact, most of Section 6 -- in the
    comp.lang.c Frequently Asked Questions (FAQ) list



    See also the rest of the FAQ; it's nutritious.

    --
    Eric.Sosman@sun .com

    Comment

    • Andreas Eibach

      #3
      Re: Arrays as function parameters and sizeof()


      "Eric Sosman" <Eric.Sosman@su n.comwrote:
      Andreas Eibach wrote:
      [... sizeof function parameter declared as array ...]
      But ... is there no other way to *compute* the actual size of the array
      (here 96) *inside* the function without expecting to have it
      "pre-chewed" by
      the calling routine?
      >
      No. Although you can write the parameter as if it were an
      array, in truth it is a pointer to an element of the array. So
      sizeof produces the size of a pointer, not the size of the thing
      pointed to nor the size of the whole array of things.
      >
      See Question 6.21 -- in fact, most of Section 6 -- in the
      comp.lang.c Frequently Asked Questions (FAQ) list
      Well I'll be DAMNED.
      A zillion FAQs in the net with having most stuff in main() and using a hell
      of global variables, but only this one covers *that* very problem.
      I stand corrected. Yes that would've been the answer I'd needed. Thanks.
      Bookmarked.

      -Andreas

      Comment

      • vippstar@gmail.com

        #4
        Re: Arrays as function parameters and sizeof()

        On Oct 31, 11:37 pm, "Andreas Eibach" <aeib...@mail.c omwrote:

        <snip>
        For an absolute beginner, this looks "working fine", but it does not. :)
        sizeof(arr) is *NOT* the size of the array (just as I too thought before),
        but merely the size of the small pointer (here it was 4). This caused the
        for loop to get exited prematurely.
        >
        The only way out with the portable solution was to write a different
        doMagic():
        >
        unsigned long doMagic (unsigned char arr[], unsigned int len);
        >
        and then *externally* enter the function using sizeof(rawdata) as length
        "info".
        This worked fine.
        >
        But ... is there no other way to *compute* the actual size of the array
        (here 96) *inside* the function without expecting to have it "pre-chewed" by
        the calling routine?
        There's some ways.
        You said the rest is intented to be 0:
        int main(void)
        {
        unsigned char rawdata[96] =
        {0x32, 0xA7, 0x53, 0x00, 0xE0, 0x20, 0x0F, 0x19,
        0x00, 0x00, 0x03, 0x70, 0x43, 0xFA, 0x00, 0x18,
        0x4E, 0xAE, 0xFF, 0xA0, 0x4A, 0x80, 0x67, 0x0A
        }; /* note, rest is _intended_ to be zeroes */
        unsigned long doMagic (unsigned char arr[])
        {
        int i;
        for(i=0; i < sizeof(arr)/(sizeof(unsigne d long)); i++)
        So you can have an end marker there.
        Ie

        unsigned char rawdata[N + 4] = { /* ... */ [N] = 1, [N + 1] = 1, [N +
        2] = 1, [N + 3] = 1 }; /* [N] = is C99 only */

        Then you can break the loop when you encounter those intentional
        zeroes, and then you read something that is not zero.
        Note your code makes assumptions about the size of unsigned long and
        the representation of it. (notice the end marker example code I gave
        suffers from the same issues)
        *(unsigned long *)rawdata may be a trap representation for example

        Comment

        Working...