Remember that unless it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" (T [N]) will be converted ("decay") to an expression of type "pointer to T" (T *), and the value of the expression will be the address of the first element of the array.
This naturally leads us to the following:
tTest *ptr = sTestStructure; // note no & operator!
The expression sTestStructure is implicitly converted from type "20-element array of tTest" to "pointer to tTest", and the value of the expression is the same as &sTestStructure[0]. To access any element of sTestStructure, you could simply index into ptr as you would sTestStructure:
ptr[i].u8Mem1 = some_value; // sTestStructure[i].u8Mem1 = some_value
printf( "%" PRIu8 "\n", ptr[j].u8Mem2 );
Remember that the subscript operation a[i] is defined as *(a + i); given the address a, offset i elements from that address and defereference the result. Thus, the [] operator implicitly dereferences ptr, which is why we use the . operator to access each struct member.
Alternately, you could also access struct members using the -> operator, and advance the pointer as necessary:
tTest *ptr = sTestStructure;
while( ptr->u8Mem1 != some_value ) // no subscript operation here
ptr++;
The expression ptr->u8Mem1 is equivalent to (*ptr).u8Mem11, which is equivalent to ptr[0].u8Mem1.
So what happens if we decide to use &sTestStructure instead? Since sTestStructure is the operand of the unary & operator, the conversion rule above doesn't apply; instead of getting a pointer to a pointer to tTest, we get a pointer to a 20-element array of tTest, or:
tTest (*arrPtr)[20] = &sTestStructure;
This presents a bit more of a challenge, since we have to dereference arrPtr before we can index into it:
(*arrPtr)[i].u8Mem1 = some_value;
printf( "%" PRIu8 "\n", (*arrPtr)[j].u8Mem2 );
Since a[i] is defined as *(a + i), the expression *arrPtr can also be written as arrPtr[0] (*arrPtr == *(arrPtr + 0) == arrPtr[0]). So those
lines could also be written as
arrPtr[0][i].u8Mem1 = some_value;
printf( "%" PRIu8 "\n", arrPtr[0][j].u8Mem2 );
As should be evident from those last couple of lines, you normally don't see this form of an array pointer unless you're dealing with multi-dimensional arrays. Remember our conversion rule, where an expression of type T [N] is converted to an expression of type T *? Well, replace T with an array type like Q[M], and we get the conversion from "N-element array of M-element array of Q" (Q [N][M]) to "pointer to M-element array of Q" (Q (*)[M]):
tTest sTestStructure[10][20];
tTest (*arrPtr)[20] = sTestStructure;
- Postfix
. has higher precedence than unary *, so *ptr.u8Mem1 would be parsed as *(ptr.u8Mem1), which is not what you want here.
sTestStructure) or pointer to array&sTestStructurewhich has typetTest (*)[20]. The first choice is far more common in C.&sTestStructurehas typetTest (*)[20], nottTest **.