Struct pointer vs. struct array pointer

Discussion in 'C Programming' started by aleksa, Feb 20, 2013.

  1. aleksa

    aleksa Guest

    Say I'm using a standard windows RECT structure...

    RECT *prect;

    // I can write
    prect->left = 0;

    // but I can also write
    prect[-1].left = 0;
    prect[0].left = 0;
    prect[1].left = 0;

    and the compiler won't complain...
    So, what did I define in the first line, a pointer to ONE structure or
    a pointer to an ARRAY of structures?

    How can I define a pointer to an array?
    I don't know in advance how many RECTs there will be in the array.

    I'm asking because I can't make WinDbg (nor MSVC debuffer) to show
    me the whole array of RECTs.

    Thanks
    aleksa, Feb 20, 2013
    #1
    1. Advertising

  2. On Wednesday, February 20, 2013 9:17:32 AM UTC, aleksa wrote:
    > Say I'm using a standard windows RECT structure...
    >
    >
    >
    > RECT *prect;
    >
    >
    > prect->left = 0;
    >

    As the code stands, prect is set to whatever random data was in the memory space assigned to it. So the second line sets a random memory location to zero. Usually the result will be a segmentation fault, but not always.

    To fix this problem

    RECT rect;
    prect = ▭

    but of course this us useless. Why not just write rect.left = 0 instead?

    >
    > How can I define a pointer to an array?
    >
    > I don't know in advance how many RECTs there will be in the array.
    >
    >

    It bcoomes useful here

    RECT rectarray[15];

    rectarray, is to all intents and purposes, a constant pointer to a block of 15 RECTs.

    So what if you don't know how many you'll need at compile time?

    RECT *rectp = malloc( Nwanted * sizeof(RECT));

    for(i=0;i<Nwanted;i++)
    rectp.left = 0;

    This creates Nwanted RECTs, and sets the left member of them all to zero.
    Nwanted can be an input value.

    --
    Read malcolm's book, Basic Algorithms
    http://www.malcolmmclean.site11.com/www
    Malcolm McLean, Feb 20, 2013
    #2
    1. Advertising

  3. On Feb 20, 10:17 am, aleksa <> wrote:
    > Say I'm using a standard windows RECT structure...
    >
    > RECT *prect;


    I hope that you initialize this pointer to actually point to some RECT
    object.

    > // I can write
    > prect->left = 0;
    >
    > // but I can also write
    > prect[-1].left = 0;
    > prect[0].left  = 0;
    > prect[1].left  = 0;
    >
    > and the compiler won't complain...
    > So, what did I define in the first line, a pointer to ONE structure or
    > a pointer to an ARRAY of structures?


    You defined prect to be a pointer to _a_ RECT object. However, nothing
    stops you from initializing it to point to the first (or any, really)
    element of a RECT array.

    The syntax

    prect[index]

    is simply defined to be a short-cut for

    *(prect+index)

    So, you're just doing pointer arithmetics followed by dereferencing.
    If your pointer were to point to the first element of an array, you
    could access this first element by

    *prect

    or alternativly by

    prect[0]

    Accessing the other array elements, however, is much more convenient
    with the latter syntax:

    prect[42]

    instead of

    *(prect+42)

    Since the elements of an array are stored contiguously, this kind of
    pointer arithmetic is exactly what you need to access the other array
    elements.

    > How can I define a pointer to an array?


    You can still use a variable of type RECT* to point to the first
    element of an array and access the other elements via the subscript
    operator. With respect to its type, it's still just a pointer to a
    single RECT. Depending on who you talk to "pointer to an array" could
    mean just that, a pointer that points to the first element of an
    array. To other people "pointer to array" means that the pointee type
    is an array type:

    int (*p)[5] = ...;

    which reads: p is a pointer to an array of 5 ints. So, there is some
    potential for confusion there ...

    Check out http://c-faq.com/aryptr/index.html for more details on this
    subject. There are a couple of things that you should know including
    array-to-pointer decay and the type transformations that are applied
    on function parameter types.

    > I don't know in advance how many RECTs there will be in the array.


    Sounds like you're in need for some dynamic buffer implementation that
    keeps track of its size and capacity and is able to grow if the
    capacity limit is reached. Unfortunately this kind of data structure
    is not part of the C standard library. Since I'm a C++ programmer who
    can simply #include <vector> I can't give you any good advice on how
    to proceed in pure C here. Rolling your own data structures is kind of
    a PITA. Maybe you'll find a useful library for that. (GLib?)

    > I'm asking because I can't make WinDbg (nor MSVC debuffer) to show
    > me the whole array of RECTs.


    That's because the type information of such a pointer doesn't really
    tell the debugger whether it points to a single object or a subobject
    of an array and how large this array is. You have to do this manually
    somehow. A decent debugger should let you evaluate custom expressions
    like yourpointer[3] so that it tells you what the 4th element of the
    array looks like, for example.
    Sebastian Gesemann, Feb 20, 2013
    #3
  4. aleksa

    James Kuyper Guest

    On 02/20/2013 04:59 AM, Malcolm McLean wrote:
    ....
    > RECT rectarray[15];
    >
    > rectarray, is to all intents and purposes, a constant pointer to a block of 15 RECTs.


    Except, of course, for the purposes of being an operand of the sizeof or
    unary & operators. It's not a pointer, it's an array. C makes it easy to
    confuse arrays and pointers; you do aleksa a disservice by actively
    promoting that confusion.
    --
    James Kuyper
    James Kuyper, Feb 20, 2013
    #4
  5. aleksa

    aleksa Guest

    On Wednesday, February 20, 2013 12:12:18 PM UTC+1, Sebastian Gesemann wrote:
    > int (*p)[5] = ...;


    Since my only concern here was how to view entire structure array
    (or at least some of it) using WinDbg, maybe this is the best:

    RECT (*prect2)[100];

    now I can view the first 100 entries, which is more than enough.

    Now, how do I assigne prect2 to point to the same memory as prect?

    prect2 = prect;
    prect2 = &prect[0];

    both work and both give me the same error
    "...differs in levels of indirection from..."
    aleksa, Feb 20, 2013
    #5
  6. aleksa <> writes:

    > On Wednesday, February 20, 2013 12:12:18 PM UTC+1, Sebastian Gesemann wrote:
    >> int (*p)[5] = ...;

    >
    > Since my only concern here was how to view entire structure array
    > (or at least some of it) using WinDbg, maybe this is the best:
    >
    > RECT (*prect2)[100];
    >
    > now I can view the first 100 entries, which is more than enough.


    If the purpose is simply to view things in a debugger it seems excessive
    to have to alter the source. Can't you use an expression in the
    debugger? I.e. where you now say something like "print prect2" could
    you not say "print *((*)[100])prect"?

    > Now, how do I assigne prect2 to point to the same memory as prect?
    >
    > prect2 = prect;
    > prect2 = &prect[0];
    >
    > both work and both give me the same error
    > "...differs in levels of indirection from..."


    prect2 = (void *)prect;

    --
    Ben.
    Ben Bacarisse, Feb 20, 2013
    #6
  7. aleksa

    James Kuyper Guest

    On 02/20/2013 07:30 AM, aleksa wrote:
    > On Wednesday, February 20, 2013 12:12:18 PM UTC+1, Sebastian Gesemann wrote:
    >> int (*p)[5] = ...;

    >
    > Since my only concern here was how to view entire structure array
    > (or at least some of it) using WinDbg, maybe this is the best:
    >
    > RECT (*prect2)[100];
    >
    > now I can view the first 100 entries, which is more than enough.
    >
    > Now, how do I assigne prect2 to point to the same memory as prect?
    >
    > prect2 = prect;
    > prect2 = &prect[0];
    >
    > both work and both give me the same error
    > "...differs in levels of indirection from..."


    prect2 = (int (*)[100])prect;

    Type punning like this is not actually guaranteed to work, but it is
    likely to. However, Ben's suggestion has the same effect without
    requiring adding a variable to your program.
    --
    James Kuyper
    James Kuyper, Feb 20, 2013
    #7
  8. Ben Bacarisse <> writes:

    > aleksa <> writes:
    >
    >> On Wednesday, February 20, 2013 12:12:18 PM UTC+1, Sebastian Gesemann wrote:
    >>> int (*p)[5] = ...;

    >>
    >> Since my only concern here was how to view entire structure array
    >> (or at least some of it) using WinDbg, maybe this is the best:
    >>
    >> RECT (*prect2)[100];
    >>
    >> now I can view the first 100 entries, which is more than enough.

    >
    > If the purpose is simply to view things in a debugger it seems excessive
    > to have to alter the source. Can't you use an expression in the
    > debugger? I.e. where you now say something like "print prect2" could
    > you not say "print *((*)[100])prect"?


    I missed the base type out: print *(int (*)[100])prect

    <snip>
    --
    Ben.
    Ben Bacarisse, Feb 20, 2013
    #8
  9. Malcolm McLean <> writes:
    > On Wednesday, February 20, 2013 9:17:32 AM UTC, aleksa wrote:
    >> Say I'm using a standard windows RECT structure...
    >> RECT *prect;
    >>
    >> prect->left = 0;
    >>

    > As the code stands, prect is set to whatever random data was in the
    > memory space assigned to it. So the second line sets a random memory
    > location to zero. Usually the result will be a segmentation fault, but
    > not always.
    >
    > To fix this problem
    >
    > RECT rect;
    > prect = &rect;
    >
    > but of course this us useless. Why not just write rect.left = 0 instead?
    >
    >> How can I define a pointer to an array?
    >>
    >> I don't know in advance how many RECTs there will be in the array.
    >>

    > It bcoomes useful here
    >
    > RECT rectarray[15];
    >
    > rectarray, is to all intents and purposes, a constant pointer to a
    > block of 15 RECTs.


    No, it bloody well is not. Do you think `sizeof rectarray` yields the
    size of a pointer?

    rectarray is an *array*. An expression of array type, in most contexts,
    is implicitly converted to a pointer to the array object's first
    element. The exceptions are when it's the operand of sizeof, _Alignof
    (new in C99), unary &, and when it's a string literal in an initializer
    used to initialize an array object.

    Malcolm and aleksa, you should both read section 6 of the comp.lang.c
    FAQ, http://www.c-faq.com/.

    > So what if you don't know how many you'll need at compile time?
    >
    > RECT *rectp = malloc( Nwanted * sizeof(RECT));


    Better:

    RECT *rectp = malloc(Nwanted * sizeof *rectp);

    (and of course you should check that malloc() returned a non-null
    pointer).

    > for(i=0;i<Nwanted;i++)
    > rectp.left = 0;
    >
    > This creates Nwanted RECTs, and sets the left member of them all to zero.
    > Nwanted can be an input value.


    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 20, 2013
    #9
  10. Sebastian Gesemann <> writes:
    > On Feb 20, 10:17 am, aleksa <> wrote:

    [...]
    >> How can I define a pointer to an array?

    >
    > You can still use a variable of type RECT* to point to the first
    > element of an array and access the other elements via the subscript
    > operator. With respect to its type, it's still just a pointer to a
    > single RECT. Depending on who you talk to


    No, it doesn't really depend on who you talk to.

    > "pointer to an array" could
    > mean just that, a pointer that points to the first element of an
    > array.


    Those people are mistaken.

    > To other people "pointer to array" means that the pointee type
    > is an array type:
    >
    > int (*p)[5] = ...;
    >
    > which reads: p is a pointer to an array of 5 ints.


    And those people are correct.

    > So, there is some
    > potential for confusion there ...


    Which is avoided by understanding the difference between a pointer
    to an element of an array and a pointer to an entire array.

    Pointers to arrays are actually not as useful as you might expect. Most
    array manipulation is done via a pointer to an element of the array --
    which means you need to keep track of the length of the array
    separately.

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 20, 2013
    #10
  11. Keith Thompson <> writes:
    [...]
    > rectarray is an *array*. An expression of array type, in most contexts,
    > is implicitly converted to a pointer to the array object's first
    > element. The exceptions are when it's the operand of sizeof, _Alignof
    > (new in C99), unary &, and when it's a string literal in an initializer
    > used to initialize an array object.


    Correction: _Alignof is new in C11, not C99.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 20, 2013
    #11
  12. aleksa

    Shao Miller Guest

    On 2/20/2013 04:17, aleksa wrote:
    > Say I'm using a standard windows RECT structure...
    >
    > RECT *prect;
    >


    As already pointed out, this should be initialized to point to a 'RECT'.

    > // I can write
    > prect->left = 0;
    >


    Which achieves the same thing as the following lines:

    (prect + 0)->left = 0;
    (*prect).left = 0;
    prect[0].left = 0;

    > // but I can also write
    > prect[-1].left = 0;


    Which achieves the same thing as the following lines:

    (prect - 1)->left = 0;
    (*(prect - 1)).left = 0;

    > prect[0].left = 0;
    > prect[1].left = 0;
    >
    > and the compiler won't complain...
    > So, what did I define in the first line, a pointer to ONE structure or
    > a pointer to an ARRAY of structures?
    >


    You declared a pointer to one 'RECT'. It can point to any 'RECT',
    including an element of an array of 'RECT's. 'prect + 1' is also a
    pointer to a 'RECT'. Whether or not a pointer actually points to a
    'RECT' is a matter of value, but its purpose is a matter of type.

    > How can I define a pointer to an array?
    > I don't know in advance how many RECTs there will be in the array.
    >
    > I'm asking because I can't make WinDbg (nor MSVC debuffer) to show
    > me the whole array of RECTs.
    >


    In the watch window, cast a pointer to the first 'RECT' as a pointer to
    an array of 'RECT's.

    (RECT (*)[100]) prect

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
    Shao Miller, Feb 20, 2013
    #12
  13. aleksa

    Shao Miller Guest

    On 2/20/2013 13:11, Shao Miller wrote:
    > On 2/20/2013 11:06, Keith Thompson wrote:
    >>
    >> rectarray is an *array*. An expression of array type, in most contexts,
    >> is implicitly converted to a pointer to the array object's first
    >> element. The exceptions are when it's the operand of sizeof, _Alignof
    >> (new in C99), unary &, and when it's a string literal in an initializer
    >> used to initialize an array object.
    >>

    >
    > You meant to type "new in C11", of course.
    >


    Which you already spotted, of course.

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
    Shao Miller, Feb 20, 2013
    #13
  14. aleksa

    aleksa Guest

    On Wednesday, February 20, 2013 7:06:27 PM UTC+1, Shao Miller wrote:
    > In the watch window, cast a pointer to the first 'RECT' as a pointer to
    > an array of 'RECT's.
    > (RECT (*)[100]) prect


    I've just tried it, it doesn't work. (using WinDbg 6.12)
    After I press enter, the line is NOT entered in the watch window.
    aleksa, Feb 20, 2013
    #14
  15. aleksa

    Shao Miller Guest

    On 2/20/2013 13:19, aleksa wrote:
    > On Wednesday, February 20, 2013 7:06:27 PM UTC+1, Shao Miller wrote:
    >> In the watch window, cast a pointer to the first 'RECT' as a pointer to
    >> an array of 'RECT's.
    >> (RECT (*)[100]) prect

    >
    > I've just tried it, it doesn't work. (using WinDbg 6.12)
    > After I press enter, the line is NOT entered in the watch window.
    >


    Did you break during the function in which 'prect' was available before
    adding the watch? If so, I apologize and will find the WinDbg method.
    To be honest, I usually cast the actual address:

    (RECT (*)[100]) 0x8042EFBE

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
    Shao Miller, Feb 20, 2013
    #15
  16. aleksa

    aleksa Guest

    On Wednesday, February 20, 2013 8:17:06 PM UTC+1, Shao Miller wrote:

    > Did you break during the function in which 'prect' was available before
    > adding the watch? If so, I apologize and will find the WinDbg method.
    > To be honest, I usually cast the actual address:
    > (RECT (*)[100]) 0x8042EFBE


    I've tried direct address, still nothing happens.
    Which version are you using?
    Or are you using something else?
    aleksa, Feb 20, 2013
    #16
  17. aleksa

    Shao Miller Guest

    On 2/20/2013 14:28, aleksa wrote:
    > On Wednesday, February 20, 2013 8:17:06 PM UTC+1, Shao Miller wrote:
    >
    >> Did you break during the function in which 'prect' was available before
    >> adding the watch? If so, I apologize and will find the WinDbg method.
    >> To be honest, I usually cast the actual address:
    >> (RECT (*)[100]) 0x8042EFBE

    >
    > I've tried direct address, still nothing happens.
    > Which version are you using?
    > Or are you using something else?
    >


    It appears that you can make a typedef and a dummy object, which is
    quite unfortunate.

    typedef RECT RECT_100[100];
    RECT_100 * dummy;

    Then your watch can have:

    (RECT_100 *) prect

    Blah.

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
    Shao Miller, Feb 20, 2013
    #17
    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. Chris Fogelklou
    Replies:
    36
    Views:
    1,352
    Chris Fogelklou
    Apr 20, 2004
  2. beetle
    Replies:
    2
    Views:
    884
    beetle
    Jan 25, 2005
  3. Zero
    Replies:
    16
    Views:
    639
    Barry Schwarz
    Nov 19, 2005
  4. , India

    pointer to an array vs pointer to pointer

    , India, Sep 20, 2011, in forum: C Programming
    Replies:
    5
    Views:
    439
    James Kuyper
    Sep 23, 2011
  5. Tuan  Bui
    Replies:
    14
    Views:
    461
    it_says_BALLS_on_your forehead
    Jul 29, 2005
Loading...

Share This Page