pointer arithmetic and user-defined types

Discussion in 'C Programming' started by Simon Morgan, Aug 17, 2005.

  1. Simon Morgan

    Simon Morgan Guest

    Can somebody please explain why the following piece of code generates an
    error unless I change q[top--] to *q[top--]:

    typedef int Queue[10];
    int top = 9;

    void insert(Queue *q, int n) {
    q[top--] = n;
    }

    $ gcc -c test.c
    test.c: In function `insert':
    test.c:5: error: incompatible types in assignment

    Seeing as q is essentially a pointer to an array I assumed that I could
    use array notation but I'm obviously mistaken so I'd just like to know why
    it doesn't work.

    Thanks.

    --
    "Being a social outcast helps you stay | ''.encode('rot-13')
    concentrated on the really important |
    things, like thinking and hacking." | [ RENT THIS SPACE ]
    - Eric S. Raymond |
    Simon Morgan, Aug 17, 2005
    #1
    1. Advertising

  2. Simon Morgan

    Netocrat Guest

    On Wed, 17 Aug 2005 13:57:40 +0000, Simon Morgan wrote:

    > Can somebody please explain why the following piece of code generates an
    > error unless I change q[top--] to *q[top--]:
    >
    > typedef int Queue[10];
    > int top = 9;
    >
    > void insert(Queue *q, int n) {
    > q[top--] = n;
    > }
    >
    > $ gcc -c test.c
    > test.c: In function `insert':
    > test.c:5: error: incompatible types in assignment
    >
    > Seeing as q is essentially a pointer to an array I assumed that I could
    > use array notation but I'm obviously mistaken so I'd just like to know why
    > it doesn't work.


    You are right that you can use array notation on the pointer, but since it
    points to an array of 10 int, indexing it results in a member with type
    array of 10 int.

    In other words, q, which is equivalent to *(q + i), has type int[10],
    to which you are attempting to assign a single int. Hence gcc complaining
    about incompatible types.

    I am going to assume that you are calling insert with the first parameter
    being something like &myqueue where myqueue is declared Queue myqueye;

    If that's the case, then the problem is not solved by *q[top--] since
    that is equivalent to *(q[top--]) when what you want is (*q)[top--].

    In other words, q[top--] results in the 10th (when in fact there is only
    one) 10-int array, and applying * to it gives the first element of that
    10-int array. Whereas (*q) results in the first (and only) 10-int array,
    and indexing that with [top--] gives the 10th int in that 10-int array.

    If my assumption is correct then there is no reason for you to pass a
    pointer to an array in the first place; you should just pass in the array
    itself. This will decay to a pointer as always but that pointer when
    indexed will result in a member with type int rather than int[10].

    So my advice is to change parameter Queue *q to Queue q unless you have a
    good reason not to.

    --
    http://members.dodo.com.au/~netocrat
    Netocrat, Aug 17, 2005
    #2
    1. Advertising

  3. Simon Morgan

    Eric Sosman Guest

    Simon Morgan wrote:
    > Can somebody please explain why the following piece of code generates an
    > error unless I change q[top--] to *q[top--]:
    >
    > typedef int Queue[10];
    > int top = 9;
    >
    > void insert(Queue *q, int n) {
    > q[top--] = n;
    > }
    >
    > $ gcc -c test.c
    > test.c: In function `insert':
    > test.c:5: error: incompatible types in assignment
    >
    > Seeing as q is essentially a pointer to an array I assumed that I could
    > use array notation but I'm obviously mistaken so I'd just like to know why
    > it doesn't work.


    See Questions 6.12 and 6.13 in the comp.lang.c
    Frequently Asked Questions (FAQ) list

    http://www.eskimo.com/~scs/C-faq/top.html

    In fact, it will probably do you good to read all
    of Section 6. If you're still confused afterwards,
    come back and ask again.

    --
    Eric Sosman, Aug 17, 2005
    #3
  4. Simon Morgan

    MadCoder Guest

    Simon Morgan wrote:

    > Can somebody please explain why the following piece of code generates an
    > error unless I change q[top--] to *q[top--]:
    >
    > typedef int Queue[10];
    > int top = 9;
    >
    > void insert(Queue *q, int n) {
    > q[top--] = n;
    > }
    >
    > $ gcc -c test.c
    > test.c: In function `insert':
    > test.c:5: error: incompatible types in assignment
    >
    > Seeing as q is essentially a pointer to an array I assumed that I could
    > use array notation but I'm obviously mistaken so I'd just like to know why
    > it doesn't work.


    exactly, q is a _pointer_ to an array.

    (*q) is the array. hence the *q[...]


    --
    ·O· Pierre Habouzit
    ··O
    OOO http://www.madism.org
    MadCoder, Aug 17, 2005
    #4
  5. Simon Morgan

    Simon Morgan Guest

    On Wed, 17 Aug 2005 16:16:26 +0200, MadCoder wrote:

    > exactly, q is a _pointer_ to an array.
    >
    > (*q) is the array. hence the *q[...]


    But isn't:

    *(q+n) == q[n]

    --
    "Being a social outcast helps you stay | ''.encode('rot-13')
    concentrated on the really important |
    things, like thinking and hacking." | [ RENT THIS SPACE ]
    - Eric S. Raymond |
    Simon Morgan, Aug 17, 2005
    #5
  6. Simon Morgan wrote:

    > On Wed, 17 Aug 2005 16:16:26 +0200, MadCoder wrote:
    >
    >> exactly, q is a _pointer_ to an array.
    >>
    >> (*q) is the array. hence the *q[...]

    >
    > But isn't:
    >
    > *(q+n) == q[n]


    I think you should read section 6. of the FAQ as suggested. you are mixing
    some different concepts.

    1- what you want :

    q is a pointer to an array
    (*q) is the array

    and if you want the n-th (well n+1-th in fact) value of the array you
    want :

    (*q)[n]

    which is roughly equivalent to

    *((*q)+n)

    2- what you don't want :

    q+n is not what you mean.
    q+n is a pointer to an array of 10 ints, that is n places after the one
    pointed by q. by places I mean offsets of sizeof(*q) == 10*sizeof(int)

    --
    ·O· Pierre Habouzit
    ··O
    OOO http://www.madism.org
    Pierre Habouzit, Aug 17, 2005
    #6
  7. Simon Morgan

    Simon Morgan Guest

    On Thu, 18 Aug 2005 00:03:26 +1000, Netocrat wrote:

    > If my assumption is correct then there is no reason for you to pass a
    > pointer to an array in the first place; you should just pass in the array
    > itself. This will decay to a pointer as always but that pointer when
    > indexed will result in a member with type int rather than int[10].
    >
    > So my advice is to change parameter Queue *q to Queue q unless you have a
    > good reason not to.


    Thanks for the explanation, your assumptions are correct. I was mistakenly
    thinking that Queue *q was a pointer to the first element of an array and
    overlooking the fact that seeing as a Queue *is* an array, that q is
    already treated as a pointer to it's first element.

    Thanks to everyone for the help.

    --
    "Being a social outcast helps you stay | ''.encode('rot-13')
    concentrated on the really important |
    things, like thinking and hacking." | [ RENT THIS SPACE ]
    - Eric S. Raymond |
    Simon Morgan, Aug 17, 2005
    #7
  8. Queue is a type of int [10] ;
    Queue * is a type of int (*) [10] ;

    use:

    void insert(Queue q, int n) {
    q[top--] = n;
    }

    or

    void insert(Queue *q, int n) {
    *q[top--] = n;
    }

    See C/C++ abstract declarators for more information.

    -- lovecreatesbeauty
    lovecreatesbeauty, Aug 18, 2005
    #8
  9. >>typedef int Queue[10];

    lovecreatesbeauty wrote:
    > Queue is a type of int [10] ;
    > Queue * is a type of int (*) [10] ;
    >
    > use:
    >
    > void insert(Queue *q, int n) {
    > *q[top--] = n;
    > }
    >


    I'm sorry for the mistake, the correct one should be:

    void insert(Queue *q, int n) {
    (*q)[top--] = n;
    }
    lovecreatesbeauty, Aug 18, 2005
    #9
    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. Sebastian Wain
    Replies:
    0
    Views:
    842
    Sebastian Wain
    Jul 13, 2004
  2. joshc
    Replies:
    5
    Views:
    552
    Keith Thompson
    Mar 31, 2005
  3. Oodini
    Replies:
    1
    Views:
    1,762
    Keith Thompson
    Sep 27, 2005
  4. Replies:
    11
    Views:
    1,398
    James Kanze
    Jun 7, 2007
  5. Francois Grieu

    Is pointer arithmetic within a struct well defined?

    Francois Grieu, Nov 29, 2013, in forum: C Programming
    Replies:
    23
    Views:
    271
    Seebs
    Dec 4, 2013
Loading...

Share This Page