From: inquisitive on
Can someone please help me to understand why the following trivial
program would segfault?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum{
black,
red
};

enum{
Hearts,
Diamonds
};

enum{
Clubs,
Spades
};


typedef struct Card
{
int color;
int suit;
int value;
}Card;

typedef Card Deck[52];

void LoadDeck(Deck * myDeck)
{

int i = 0;
for(; i < 51; i++)
{
myDeck[i]->color = i % 2;
myDeck[i]->suit = i % 4;
myDeck[i]->value = i % 13;
}
}

void PrintDeck(Deck * myDeck)
{
int i = 0;
for(;i < 52; i++)
{
printf("Card %d %d %d\n",myDeck[i]->color, myDeck[i]->suit,
myDeck[i]->value);
}
}

int main()
{
Deck myDeck;
memset(&myDeck,0,sizeof(Deck));
LoadDeck(&myDeck);
PrintDeck(&myDeck);
return 0;
}


It appears to segfault on this line.
myDeck[i]->color = i % 2;
But only when i equals 2.

Any ideas on what I've done wrong here?

By the way I'm just trying to create a standard 52 card deck.
From: Ike Naar on
In article <ab5ba7b0-aaed-4d20-84ca-873ca06b23db(a)b31g2000prb.googlegroups.com>,
<inquisitive(a)mailinator.com> wrote:
>Can someone please help me to understand why the following trivial
>program would segfault?
> /* [snip] */
>
>typedef struct Card
>{
> int color;
> int suit;
> int value;
>}Card;
>
>typedef Card Deck[52];
>
>void LoadDeck(Deck * myDeck)
>{
>
> int i = 0;
> for(; i < 51; i++)
> {
> myDeck[i]->color = i % 2;

(*myDeck)[i].color = i % 2; /* see below */

> myDeck[i]->suit = i % 4;
> myDeck[i]->value = i % 13;
> }
>}

In LoadDeck, myDeck is a pointer to Deck; *myDeck is a Deck,
i.e. an array of Card.
(*myDeck)[i] is the i-th Card in that array;
and (*myDeck)[i].color is the color member of that Card.

Ike
From: Ben Bacarisse on
inquisitive(a)mailinator.com writes:

> Can someone please help me to understand why the following trivial
> program would segfault?

Basically, you have one too many levels of pointer.

> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> enum{
> black,
> red
> };
>
> enum{
> Hearts,
> Diamonds
> };
>
> enum{
> Clubs,
> Spades
> };

This is not right since (in C) both Clubs and Hearts are the same
value (0).

> typedef struct Card
> {
> int color;
> int suit;
> int value;
> }Card;

Again, a little odd to separate the colour from the suit, but that is
not really a problem.

> typedef Card Deck[52];
>
> void LoadDeck(Deck * myDeck)

But this is. You want to pass a pointer to Card, not a Deck.
Alternatively, if you really do want to pass a Deck * (there is no
point, but it is legal to do so) you must access the cards within
that deck like this:

(*myDeck)[i].value = i % 13;

and so on. But really I'd use:

void LoadDeck(Card *myDeck)

and inside the access becomes:

myDeck[i].value = i % 13;

You can use your typedef, but that obscures the fact that the
parameter is a pointer to the first element of an array:

void LoadDeck(Deck myDeck) /* note no *. Obscure and not advised. */

> {
>
> int i = 0;
> for(; i < 51; i++)

I think you mean 52 here.

> {
> myDeck[i]->color = i % 2;
> myDeck[i]->suit = i % 4;
> myDeck[i]->value = i % 13;
> }
> }
>
> void PrintDeck(Deck * myDeck)
> {
> int i = 0;
> for(;i < 52; i++)
> {
> printf("Card %d %d %d\n",myDeck[i]->color, myDeck[i]->suit,
> myDeck[i]->value);
> }
> }
>
> int main()

In C it is better to write:

int main(void)

> {
> Deck myDeck;
> memset(&myDeck,0,sizeof(Deck));
> LoadDeck(&myDeck);
> PrintDeck(&myDeck);

What you write here depends on how you solve the problems above, but
if you go with the simplest option, all the & can be removed.

> return 0;
> }

--
Ben.
From: Bart van Ingen Schenau on
inquisitive(a)mailinator.com wrote:

> Can someone please help me to understand why the following trivial
> program would segfault?
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> enum{
> black,
> red
> };
>
> enum{
> Hearts,
> Diamonds
> };
>
> enum{
> Clubs,
> Spades
> };
>
>
> typedef struct Card
> {
> int color;
> int suit;
> int value;
> }Card;
>
> typedef Card Deck[52];
>
> void LoadDeck(Deck * myDeck)

Here you declare myDeck as a pointer to an array of 52 Card objects.

> {
>
> int i = 0;
> for(; i < 51; i++)
> {
> myDeck[i]->color = i % 2;
> myDeck[i]->suit = i % 4;
> myDeck[i]->value = i % 13;

This looks like you try to access 52 arrays of a single Card pointer
each.
This should be:
(*myDeck)[i].color = i % 2;
(*myDeck)[i].suit = i % 4;
(*myDeck)[i].value = i % 13;

and similar in PrintDeck.

<snip>
> It appears to segfault on this line.
> myDeck[i]->color = i % 2;
> But only when i equals 2.

That is just coincidence. It could just as easily have segfaulted with
any other value of i > 0.

>
> Any ideas on what I've done wrong here?

Due to the 'typedef Card Deck[52]', you got your use of array indexing
wrong. That is one of the big pitfalls when using a typedef for an
array type.

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
From: Fabiano on


inquisitive(a)mailinator.com ha scritto:

> int main()
> {
> Deck myDeck;
> memset(&myDeck,0,sizeof(Deck));
> LoadDeck(&myDeck);
> PrintDeck(&myDeck);
> return 0;
> }
I suppose...
myDeck is an array, "myDeck" is a pointer yet to the array.

try
> memset(myDeck,0,sizeof(Deck));
> LoadDeck(myDeck);
> PrintDeck(myDeck);

Am I right?
 |  Next  |  Last
Pages: 1 2
Prev: CVAPI(void)
Next: solutions manuals