10

New to pointers and C and need for my program a pointer for an array of structs and be able to pass this pointer to a function.

What is the correct way to declare a pointer of struct array type and what should be my function parameter that can take such pointer?

This is my attempt:

#define HAND_SIZE 5

struct Card {
    char suit;
    char face;
};

void printHandResults(struct Card *hand[HAND_SIZE]);

int main(void)
{
    struct Card hand[HAND_SIZE];
    struct Card (*handPtr)[HAND_SIZE]; //Correct way to declare?
    handPtr = &hand; 
    ...
    printHandResults(handPtr);

}
void printHandResults(struct Card *hand[HAND_SIZE]) {
...
}

And this is the warning I get:

warning: incompatible pointer types passing 'struct Card (*)[5]' to parameter of type 'struct Card **' [-Wincompatible-pointer-types]

I understand the pointers are different types but I cant seem to figure out how to set it correctly.

I'll appreciate if someone can *pointer me in the right direction.

6
  • Arrays automatically become pointers when they're passed to a function, you don't need a separate variable for this. Commented Nov 8, 2016 at 1:57
  • 2
    struct Card *hand[HAND_SIZE] is an array of pointers, not a pointer to an array. Commented Nov 8, 2016 at 1:58
  • handPtr in your way is array of pointer. Why wouldn't you just pass &hand to printHandResults? Commented Nov 8, 2016 at 1:58
  • 1
    Why do you want a pointer to an array? Arrays are usually manipulated using pointers to the element type, not to the array as a whole. That's not to say that array pointers are never useful, but element pointers are far more common. Commented Nov 8, 2016 at 2:46
  • @KeithThompson - He may need to change the array in the callee. Commented Nov 9, 2016 at 6:45

3 Answers 3

6

An array degrades into a raw pointer to the first array element. So you can do something more like this instead:

#define HAND_SIZE 5

struct Card {
    char suit;
    char face;
};

void printHandResults(struct Card *hand);

int main(void)
{
    struct Card hand[HAND_SIZE];
    ...
    printHandResults(hand);
}

void printHandResults(struct Card *hand)
{
    for (int i = 0; i < HAND_SIZE; ++i)
    {
        // print hand[i].suit and hand[i].face as needed...
    }
}

Alternatively:

#define HAND_SIZE 5

struct Card {
    char suit;
    char face;
};

void printHandResults(struct Card *hand, int numInHand);

int main(void)
{
    struct Card hand[HAND_SIZE];
    ...
    printHandResults(hand, HAND_SIZE);
}

void printHandResults(struct Card *hand, int numInHand)
{
    for (int i = 0; i < numInHand; ++i)
    {
        // print hand[i].suit and hand[i].face as needed...
    }
}

Alternatively, create a new typedef for the card array, and then you can create variables and pointers of that type:

#define HAND_SIZE 5

struct Card {
    char suit;
    char face;
};

typedef struct Card Hand[HAND_SIZE];

void printHandResults(Hand *hand);

int main(void)
{
    Hand hand;
    ...
    printHandResults(&hand);
}

void printHandResults(Hand *hand)
{
    for (int i = 0; i < HAND_SIZE; ++i)
    {
        // print hand[i].suit and hand[i].face as needed...
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks this makes sense.Why the second int parameter?
The second parameter is to know the size of the actual array in the called function.
I see. But given I already have it as a constant HAND_SIZE and could use it from function body do I still need it as a parameter in the function? Please explain.
Sure, if you always have HAND_SIZE number of cards in the hand being printed. But having the second parameter allows the function to be more flexible so it can print different hand sizes. Say you want to print the cards before a full hand is dealt. Or you want to implement multiple card games that use different number of cards per hand.
6

Maybe what you want is to do this:

void printHandResults(struct Card (*hand)[]);

and this:

void printHandResults(struct Card (*hand)[]) {

}

What you were doing was passing a pointer to an array of struct variables in the main, BUT, the function was set to receive an array of pointers to struct variables and not a pointer to an array of struct variables! Now the type mismatch would not occur and thus, no warning.

Note that [], the (square) brackets have higher precedence than the (unary) dereferencing operator *, so we would need a set of parentheses () enclosing the array name and * operator to ensure what we are talking about here!

3 Comments

Thanks. I'll experiment with this in my program.
@Angew: You are doing this in C++ on the online IDE. The question is about the same functionality in C.
@skrtbhtngr Sorry, I didn't realise changing g++ to gcc is not enough when the file ends in .cpp.
0

More easy way:

#define HAND_SIZE 5

typedef struct Cards{
   char suit;
   char face;
}card_t;

void printHandResults( card_t*);

int main(void)
{
   card_t hand[HAND_SIZE];
   card_t* p_hand = hand;
...
   printHandResults(p_hand);

}
void printHandResults( card_t *hand)
{
 // Here you must play with pointer's arithmetic 
...
}

1 Comment

Could you, please, explain in the code which pointer's arithmetic did you mean.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.