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.
     
    Simon Morgan, Aug 17, 2005
    #1
    1. Advertisements

  2. Simon Morgan

    Netocrat Guest

    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.
     
    Netocrat, Aug 17, 2005
    #2
    1. Advertisements

  3. Simon Morgan

    Eric Sosman Guest

    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

    exactly, q is a _pointer_ to an array.

    (*q) is the array. hence the *q[...]
     
    MadCoder, Aug 17, 2005
    #4
  5. Simon Morgan

    Simon Morgan Guest

    But isn't:

    *(q+n) == q[n]
     
    Simon Morgan, Aug 17, 2005
    #5
  6. 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)
     
    Pierre Habouzit, Aug 17, 2005
    #6
  7. Simon Morgan

    Simon Morgan Guest

    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.
     
    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];
    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. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.