struct z_st {int a ; char b}; typedef struct z_st Zarr_k[10]; Zarr aZ; struct z_st bZ[10]; aZ and bZ are considered different types. Why?

46 views Asked by At

I am trying to pass pointers to arrays of structures, but the arrays are defined in two different ways. I am struggling to make sense of which syntax to use in each case and why.

When I try to compile this with GCC I get the following error messages. I would have thought that aZ and bZ are essentially the same and that the syntax for each would be essentially the same but not so. How should I be thinking about this?

I tried different approaches to defining a pointer to the two 'equivalent' variables, and to passing those pointers to functions. I found an approach that works, but I don't know why.

struct z_st {int i ; char c  ; } ;
typedef struct z_st Zarr_k[10] ;

int foo( Zarr_k *pz ) { 
    return (*pz)[0].i++ ;   // pz->[0].i gives an error 
}
int bar ( struct z_st barz[10] ) { 
    return barz[0].i ;  
}
int main (int argc, char *argv[] ) {
   int ra,rb ; 
    struct z_st aZ[10];  // aZ is a 10-array of structs type z_st
    Zarr_k      bZ    ;     // bZ is a
    struct z_st *paz = &aZ[0] ;     // &az    does not work; incompatible pointer type  
    Zarr_k      *pbz = &bZ ;        // &bZ[0] does not work; incompatible pointer type
    ra = foo(paz) ;                     // gives compile error/warning.
    rb = foo(pbz) ;                     // Ok
    ra = bar(paz) ;                     // OK
    rb = bar(pbz) ;                 // error 
    return 0 ; 
}

The compiler warnings and errors are:

> struct_type_clash.c:16:18: warning: passing argument 1 of ‘foo’ from incompatible pointer type [-Wincompatible-pointer-types]
> 16 |         ra = foo(paz) ;  // gives compile error/warning.
>       |                  ^~~
>       |                  |
> struct z_st *
> struct_type_clash.c:4:18: note: expected ‘struct z_st (*)[10]’ but argument is of type ‘struct z_st *’
> 4 | int foo( Zarr_k *pz ) {
>       |          ~~~~~~~~^~
> struct_type_clash.c:19:18: warning: passing argument 1 of ‘bar’ from incompatible pointer type [-Wincompatible-pointer-types]
> 19 |         rb = bar(pbz) ; // error
>       |                  ^~~
>      |
      |                  struct z_st (*)[10]
> struct_type_clash.c:7:23: note: expected ‘struct z_st *’ but argument is of type ‘struct z_st (*)[10]’
> 7 | int bar ( struct z_st barz[10] ) {
1

There are 1 answers

1
dave_thompson_085 On

You wrote *.

In C Zarr_k *pz declares a pointer to an array of 10 structs — equivalent to struct z_st (*pz)[10]. By contrast, struct z_st barz[10] as a function parameter declares a pointer directly to a struct, not an array; this is because a parameter declared with array type is 'rewritten' to be a pointer to the element type of that array, in much the same fashion that an array object is almost always converted to a pointer to its first element, commonly called 'decay'.

The error message tells you this, although you have incorrectly posted it as quoted text rather than code, causing some of the asterisks to disappear.

int foo( Zarr_k pz ) gives the same type as your current bar namely struct z_st *

int bar ( struct z_st (*barz)[10] ) gives the same type as your current foo