pointer arithmetic and user-defined types

S

Simon Morgan

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.
 
N

Netocrat

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.
 
E

Eric Sosman

Simon said:
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.
 
M

MadCoder

Simon said:
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[...]
 
P

Pierre Habouzit

Simon said:
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)
 
S

Simon Morgan

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.
 
L

lovecreatesbeauty

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
 
L

lovecreatesbeauty

typedef int Queue[10];
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;
}
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top