Parse "Card * const wDeck"

D

DaveLessnau

I'm trying to learn C on my own and, apparently, my brain went on
vacation somewhere. I just can't figure out how to parse the following
function call:

"void fillDeck( Card * const wDeck, const char * wFace[], const char *
wSuit[])"

Card is aliased before that call with:

"typedef struct card Card"

the card structure is define before that with:

"struct card {
const char *face;
const char *suit;
};"

and the paramter passed via wDeck is defined in main as:

"Card deck[ 52 ]" /* an array of 52 card structures */

Looking around the web, this seems to be a fairly standard example
program. In that call to fillDeck, the first parameter seems to parse
as sending a pointer to an instance of type Card (in this case, the
address to the first Card in the 52 element array of Cards) but making
sure the receiving function can't modify it (with the "const"
modifier). I've got to be reading that wrong, because the sole purpose
of fillDeck is to modify wDeck by filling it using a for loop:

"for ( i = 0; i <= 51; i++ ) {
wDeck[ i ].face = wFace[i % 13 ];
...."

Can anyone shed some light on how I'm misreading that function call?
Probably related to it: can anyone tell me why the dereferencing
operator * is separated from its variable? IOW, why

"void fillDeck( Card * const wDeck,..."

instead of

"void fillDeck( Card *const wDeck,..." (*const instead of * const)

or, heck,

"void fillDeck( Card const *wDeck,..." (const *wDeck instead of * const
wDeck)?
 
M

Mike Wahler

DaveLessnau said:
I'm trying to learn C on my own and, apparently, my brain went on
vacation somewhere. I just can't figure out how to parse the following
function call:

"void fillDeck( Card * const wDeck, const char * wFace[], const char *
wSuit[])"

That's not a function call, but a declaration (which is
missing the terminating semicolon. It declares:

'fillDeck' is a function which does not return a value, and
takes three arguments:

1. A constant pointer ('constant' meaning that its value is not
allowed to be changed) to an object of type 'wDeck'.

2. A pointer to a constant object of type 'char'.

3. A pointer to a constant object of type 'char'.

Card is aliased before that call with:

"typedef struct card Card"

the card structure is define before that with:

"struct card {
const char *face;
const char *suit;
};"

and the paramter passed via wDeck is defined in main as:

"Card deck[ 52 ]" /* an array of 52 card structures */

The name of an array, used in a value context (one of which
is passing it as a function argument), automatically converts
to a pointer to its first element. So the call:

fillDeck(deck, /* other args */);

causes the address of 'deck[0]' (the first array element)
to be passed as the first argument.
Looking around the web, this seems to be a fairly standard example
program. In that call to fillDeck, the first parameter seems to parse
as sending a pointer to an instance of type Card (in this case, the
address to the first Card in the 52 element array of Cards) but making
sure the receiving function can't modify it (with the "const"
modifier).

It must not modify the pointer value, modifying what
it points to is fine.
I've got to be reading that wrong,
Perhaps.

because the sole purpose
of fillDeck is to modify wDeck by filling it using a for loop:

Yes, the elements of the array are modified, but the pointer
containing its address is not.
"for ( i = 0; i <= 51; i++ ) {
wDeck[ i ].face = wFace[i % 13 ];
..."

Can anyone shed some light on how I'm misreading that function call?

See above.
Probably related to it: can anyone tell me why the dereferencing
operator * is separated from its variable? IOW, why

"void fillDeck( Card * const wDeck,..."

instead of

"void fillDeck( Card *const wDeck,..." (*const instead of * const)

That's a syntactical issue. The whitespace is not germane. Equally
valid, and having the same meaning:

Card*const wDeck

Card * const wDeck


Card
*
const
wDeck

/* etc */
or, heck,

"void fillDeck( Card const *wDeck,..." (const *wDeck instead of * const
wDeck)?

Now you've changed the syntax. The placement of the asterisk
with respect to the const modifier affects the meaning.

Using type 'int' for simplicity's sake:

int *p; /* non-const pointer to non-constant int */
const int *p; /* non-const pointer to constant int */
int const *p; /* non-const pointer to constant int */
int * const p; /* constant pointer to non-constant int */
const int * const p; /* constant pointer to constant int */
int const * const p; /* constant pointer to constant int */

Note that in the case where 'const' appears to the left of
the asterisk, placing it before or after the 'int' does
not change the meaning.


-Mike
 
D

DaveLessnau

Thanks. Amongs my key misunderstandings was "Yes, the elements of the
array are modified, but the pointer containing its address is not." I
was mixing up the addresses and the values. Also, your table at the
end showing the differences between constant/non-constant pointers to
constant/non-constant values helped tremendously.

Thanks again.
 
P

Peter Shaggy Haywood

Groovy hepcat Mike Wahler was jivin' on Mon, 10 Jan 2005 23:30:23 GMT
in comp.lang.c.
Re: Parse "Card * const wDeck"'s a cool scene! Dig it!
DaveLessnau said:
"void fillDeck( Card * const wDeck, const char * wFace[], const char *
wSuit[])"

'fillDeck' is a function which does not return a value, and
takes three arguments:

1. A constant pointer ('constant' meaning that its value is not
allowed to be changed) to an object of type 'wDeck'.

That's a const pointer to type Card. wDeck is the name of the
parameter.

[Snip.]
That's a syntactical issue. The whitespace is not germane. Equally
valid, and having the same meaning:

It's a style issue, rather than a syntactical one. The syntax allows
either. As you say, the white space is not germane.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 
E

E. Robert Tisdale

DaveLessnau said:
I'm trying to learn C on my own
[but] apparently, my brain went on vacation somewhere.
I just can't figure out how to parse the following function call:

void fillDeck(Card*const wDeck,
const char* wFace[], const char* wSuit[]);

Card is aliased before that call with:

typedef struct Card Card;

the card structure is define before that with:

struct Card {
const char *face;
const char *suit;
};

and the paramter passed via wDeck is defined in main as:

Card deck[ 52 ]; // an array of 52 card structures
Looking around the web,
this seems to be a fairly standard example program.

Unfortunately, it is a very poor design as well as a very common design.
In that call to fillDeck, the first parameter seems to parse
as sending a pointer to an instance of type Card (in this case,
the address to the first Card in the 52 element array of Cards)
but making sure the receiving function can't modify it
(with the "const" modifier). I've got to be reading that wrong,
because the sole purpose of fillDeck
is to modify wDeck by filling it using a for loop:
for (size_t i = 0; i < 52; ++i) {
wDeck.face = wFace[i%13];
// ...

Can anyone shed some light on how I'm misreading that function call?
Probably related to it: can anyone tell me why the dereferencing
operator * is separated from its variable? IOW, why

void fillDeck(Card*const wDeck, ...

instead of

void fillDeck(Card *const wDeck, ... // (*const instead of * const)

or, heck,

void fillDeck(Card const *wDeck, ... // (const *wDeck instead of * const
wDeck)?


A better design would be

typedef struct Deck {
Card deck[52];
} Deck;

Deck Deck_create(const char* wFace[], const char*wSuit[]) {
Deck deck;
for (size_t i = 0; i < 52; ++i) {
deck.deck.face = wFace[i%13];
// ...
}
return deck;
}

Which you could call like this:

Deck wDeck = Deck_create(wFace, wSuit);

instead of like this:

Deck wDeck;
fillDeck(wDeck.deck, wFace, wSuit);
 
M

Mike Wahler

Peter "Shaggy" Haywood said:
Groovy hepcat Mike Wahler was jivin' on Mon, 10 Jan 2005 23:30:23 GMT
in comp.lang.c.
Re: Parse "Card * const wDeck"'s a cool scene! Dig it!
DaveLessnau said:
"void fillDeck( Card * const wDeck, const char * wFace[], const char *
wSuit[])"

'fillDeck' is a function which does not return a value, and
takes three arguments:

1. A constant pointer ('constant' meaning that its value is not
allowed to be changed) to an object of type 'wDeck'.

That's a const pointer to type Card. wDeck is the name of the
parameter.

Oops. :)
[Snip.]
That's a syntactical issue. The whitespace is not germane. Equally
valid, and having the same meaning:

It's a style issue, rather than a syntactical one.

Style of syntax, OK? :)
The syntax allows
either. As you say, the white space is not germane.


-Mike
 
M

Mike Wahler

E. Robert Tisdale said:
A better design would be

typedef struct Deck {
Card deck[52];
} Deck;

IMO even better would be to dump the array and use a container.

-Mike
 
K

Keith Thompson

Mike Wahler said:
E. Robert Tisdale said:
A better design would be

typedef struct Deck {
Card deck[52];
} Deck;

IMO even better would be to dump the array and use a container.

What do you mean by "container"? Are you thinking of C++?
 
E

E. Robert Tisdale

Keith said:
Mike said:
E. Robert Tisdale said:
A better design would be

typedef struct Deck {
Card deck[52];
} Deck;

IMO even better would be to dump the array and use a container.

What do you mean by "container"?

A container is an object that contains objects of some type.
An array is an example of a container.
A list is a container.
A queue is a container.

I believe that Mike is correct.
A container for a Deck of Card's would be even better
but I didn't want to confuse the issue
which I believe was the return value.
 
K

Keith Thompson

E. Robert Tisdale said:
Keith said:
Mike said:
E. Robert Tisdale wrote:

A better design would be

typedef struct Deck {
Card deck[52];
} Deck;

IMO even better would be to dump the array and use a container.
What do you mean by "container"?

A container is an object that contains objects of some type.
An array is an example of a container.
A list is a container.
A queue is a container.

Thanks, but I was asking Mike Wahler what *he* meant by "container".
 
M

Mike Wahler

Keith Thompson said:
Mike Wahler said:
E. Robert Tisdale said:
A better design would be

typedef struct Deck {
Card deck[52];
} Deck;

IMO even better would be to dump the array and use a container.

What do you mean by "container"? Are you thinking of C++?

Yes, I seem to be lost again, dammit. :)

Thanks for the heads-up.

-Mike
 
M

Mike Wahler

E. Robert Tisdale said:
Keith said:
Mike said:
E. Robert Tisdale wrote:

A better design would be

typedef struct Deck {
Card deck[52];
} Deck;

IMO even better would be to dump the array and use a container.

What do you mean by "container"?

A container is an object that contains objects of some type.
An array is an example of a container.
A list is a container.
A queue is a container.

I believe that Mike is correct.
A container for a Deck of Card's would be even better
but I didn't want to confuse the issue
which I believe was the return value.

No, Keith's assumption was correct, I was talking about
a C++ standard library container, and forgot where I was.


-Mike
 
C

CBFalconer

Mike said:
.... snip ...

No, Keith's assumption was correct, I was talking about
a C++ standard library container, and forgot where I was.

Failure to discriminate between a ladies tea and a cathouse has
been known to lead to embarassing moments.
 
P

pete

E. Robert Tisdale said:
Keith said:
Mike said:
E. Robert Tisdale wrote:

A better design would be

typedef struct Deck {
Card deck[52];
} Deck;

IMO even better would be to dump the array and use a container.

What do you mean by "container"?

A container is an object that contains objects of some type.
An array is an example of a container.
A list is a container.
A queue is a container.

Arrays are objects.
Lists and queues aren't objects.
 
D

dandelion

pete said:
E. Robert Tisdale wrote:

The above is C++ or rather OOA/D jargon, which does not (or very poorly)
translate into the sequential approach of imperative languages like C.
Arrays are objects.
Lists and queues aren't objects.

Hence the confusion.
 
L

Lawrence Kirby

Keith Thompson wrote:

....


A container is an object that contains objects of some type.
An array is an example of a container.
A list is a container.
A queue is a container.

I believe that Mike is correct.
A container for a Deck of Card's would be even better

By your definition a container for a deck of cards would be able to hold a
number of decks of cards, which is probably not needed. Here Deck is in
effect a container for cards, although not with all the OO baggage.

Lawrence
 
M

Mike Wahler

CBFalconer said:
Failure to discriminate between a ladies tea and a cathouse has
been known to lead to embarassing moments.

Unless the tea is held in said cathouse. :)

(Some amusing metaphors spring to mind, but
decorum prohibits me expressing them here. :) )

-Mike
 
E

E. Robert Tisdale

Lawrence said:
By your definition a container for a deck of cards would be able to hold a
number of decks of cards, which is probably not needed. Here Deck is in
effect a container for cards, although not with all the OO baggage.

I would gladly carry "the OO baggage" in this case.
 

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

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top