# Exercise 5-9 K&R

Discussion in 'C Programming' started by mdh, Aug 3, 2007.

1. ### mdhGuest

May I ask two questions relating to this exercise? ( asking to repeat
the example using pointers)

Given a 2-dimensional array:

char a[2][13] ( which is initialized in the exercise to represent days
of the month in a leap/non-leap year)

Part of the answer ( in Tondo and Gimpel) includes "assigning" a char
pointer to the correct "row" thus:

char *p
p = a[leap]; ( with "leap" either 0 or 1);

Question.

If "a" is "converted" to a pointer to element 0 of row 1, then a[1]
points p to element 0 of row 2? Is this the correct way of visualizing
this?

2nd question involves pointer arithmetic.
In order to calculate the difference between a[leap] and the current
position of "p" the expression

*pmonth = p - *(a + leap ) is used. ( again, "leap" is 0 or 1)
( *pmonth is a ptr of type integer declared as such in the parameter
of the function)

Question:

I can see how p represents an address of the "pth" element of "a" and
that this should simply be the difference between 2 pointers.
However, the syntax

*(a + leap) is the one that is confusing to me. I thought the "*" is
the dereferencing operator, and as such, it should be (a + p) and
not *(a+p).

mdh, Aug 3, 2007

2. ### mdhGuest

<I should have included the original code...sorry. Included below.>

May I ask two questions relating to this exercise? ( asking to repeat
the example using pointers)
Given a 2-dimensional array:

char a[2][13] ( which is initialized in the exercise to represent
days
of the month in a leap/non-leap year)

Part of the answer ( in Tondo and Gimpel) includes "assigning" a char
pointer to the correct "row" thus:

char *p
p = a[leap]; ( with "leap" either 0 or 1);

Question.

If "a" is "converted" to a pointer to element 0 of row 1, then a[1]
points p to element 0 of row 2? Is this the correct way of
visualizing
this?

2nd question involves pointer arithmetic.
In order to calculate the difference between a[leap] and the current
position of "p" the expression

*pmonth = p - *(a + leap ) is used. ( again, "leap" is 0 or 1)
( *pmonth is a ptr of type integer declared as such in the parameter
of the function)

Question:

I can see how p represents an address of the "pth" element of "a" and
that this should simply be the difference between 2 pointers.
However, the syntax

*(a + leap) is the one that is confusing to me. I thought the "*" is
the dereferencing operator, and as such, it should be (a + p) and
not *(a+p).

>>>>>>>>

#include <stdio.h>

static char daytab[2][13]={
{0,31,28,31,30,31,30,31,31,31,30,31,30},
{0,31,29,31,30,31,30,31,31,31,30,31,30}
};

void month_day( int yearday, int year, int *pmnth, int *pday);

int main (int argc, const char * argv[]) {
int mnth, day;

printf("The Day of the year for \"12th Dec 1957\" is %d\n",
day_of_year(1957, 12, 12) );
month_day(228, 1957, &mnth, &day );
printf("The Day 228 of the year 1957 was day %d of month %d", day,
mnth);

return 0;
}

/* day_of_year*/

int day_of_year(int year, int month, int day){

int leap;
char *p;

leap = year % 4==0 && year % 100 != 0 || year %400 == 0;
p=daytab[leap];

while ( --month)
day += *++p;

return day;

}

/* set the month and day, from day of year */

void month_day( int yearday, int year, int *pmnth, int *pday){

int leap;
char *p;

leap= year % 4==0 && year % 100 != 0 || year %400 == 0;
p=daytab[leap];

while ( yearday > *++p)
yearday -= *p;

*pmnth = p -*(daytab+leap);
*pday = yearday;
}

mdh, Aug 3, 2007

3. ### Army1987Guest

On Thu, 02 Aug 2007 20:06:31 -0700, mdh wrote:

> May I ask two questions relating to this exercise? ( asking to repeat
> the example using pointers)
>
> Given a 2-dimensional array:
>
> char a[2][13] ( which is initialized in the exercise to represent days
> of the month in a leap/non-leap year)
>
> Part of the answer ( in Tondo and Gimpel) includes "assigning" a char
> pointer to the correct "row" thus:
>
> char *p
> p = a[leap]; ( with "leap" either 0 or 1);
>
> Question.
>
> If "a" is "converted" to a pointer to element 0 of row 1, then a[1]
> points p to element 0 of row 2? Is this the correct way of visualizing
> this?

a is a char [2][13], which is converted to a char (* )[13].
Thus a + 1 points to the second char [13] in the array, that is
to the second row.
a[1], that is *(a + 1), is a char [13], which is converted to
a char * pointing to a[1][0]. Got it?
> 2nd question involves pointer arithmetic.
> p is advanced using *++p.
> In order to calculate the difference between a[leap] and the current
> position of "p" the expression
>
> *pmonth = p - *(a + leap ) is used. ( again, "leap" is 0 or 1)
> ( *pmonth is a ptr of type integer declared as such in the parameter
> of the function)
>
> Question:
>
> I can see how p represents an address of the "pth" element of "a" and
> that this should simply be the difference between 2 pointers.
> However, the syntax
>
> *(a + leap) is the one that is confusing to me. I thought the "*" is
> the dereferencing operator, and as such, it should be (a + p) and
> not *(a+p).

*(a + p) is the same as a[p]. Remember which a is an array [2] of
arrays [13] of chars, so it evaluates to a pointer to an array
[13] of chars. *(a + 0) = *a is the first line of a, that is a
char [13], and it evaluates to a pointer to its first element,
i.e. &a[0][0]. Similarly *(a + 1) is a[1], which evaluates to
&a[1][0].
--
Army1987 (Replace "NOSPAM" with "email")
"Never attribute to malice that which can be adequately explained
by stupidity." -- R. J. Hanlon (?)

Army1987, Aug 3, 2007
4. ### mdhGuest

> mdh wrote:
> >
> > char *p
> > p = a[leap]; ( with "leap" either 0 or 1);

>
> > Question.

>
> > If "a" is "converted" to a pointer to element 0 of row 1, then a[1]
> > points p to element 0 of row 2? Is this the correct way of visualizing
> > this?

Army1987 <> wrote:
>
> a is a char [2][13], which is converted to a char (* )[13].
> Thus a + 1 points to the second char [13] in the array, that is
> to the second row.
> a[1], that is *(a + 1), is a char [13], which is converted to
> a char * pointing to a[1][0]. Got it?

Yes...I think so. So, there are 2 "levels" of conversion? Is this
then true? Given that conceptually one can imagine this object ( char
a[2][13] ) as array 2 of 13 chars (each), calling the name "a"
converts to a pointer of type array 13 to char. Hence manipulating
this, whether by indexing or pointers will change the "row". Invoking
the name "a[]" converts to a char pointer, hence char *p is able to
access each individual character of a given "row"?

> > mdh wrote:
> > 2nd question involves pointer arithmetic.
> > p is advanced using *++p.
> >

>
> > Question:

>
> > I can see how p represents an address of the "pth" element of "a" and
> > that this should simply be the difference between 2 pointers.
> > I thought..... it should be (a + p) and not *(a+p).

>

Got it...just the reverse of the above.
Thanks.

BTW...great quote !

> "Never attribute to malice that which can be adequately explained
> by stupidity." -- R. J. Hanlon (?)

mdh, Aug 3, 2007
5. ### Army1987Guest

On Fri, 03 Aug 2007 09:32:54 -0700, mdh wrote:
> Army1987 <> wrote:
>>
>> a is a char [2][13], which is converted to a char (* )[13].
>> Thus a + 1 points to the second char [13] in the array, that is
>> to the second row.
>> a[1], that is *(a + 1), is a char [13], which is converted to
>> a char * pointing to a[1][0]. Got it?

>
>
> Yes...I think so. So, there are 2 "levels" of conversion?

Depends on what you mean.
a is a char [2][13] and gets converted to a char (*)[13].
*a is a char [13] and gets converted to a char *.
But the fact that you can write **a does NOT mean that a is ever
converted to a char **. If an implementation had different sizes
for pointers to pointers and pointers to arrays, sizeof(a + 0)
would return the former. Also you could not assign a to a char **.
**a works because it binds as *(*a), and *a has type char [13]
before conversion and char * after conversion.
Similarly, the fact that you can write
#include <stdio.h>
int main(void)
{
(
*******
* * *
* * *
* * *
* * * * *
* * *
*******
puts)("Peace!");
return 0;
}
doesn't mean puts is ever converted to a 31th-level pointer to
function returning int and taking a const char *.

Army1987, Aug 5, 2007
6. ### mdhGuest

On Aug 5, 4:01 am, Army1987 <> wrote:
>
> > Yes...I think so. So, there are 2 "levels" of conversion?

>
> Depends on what you mean.
> a is a char [2][13] and gets converted to a char (*)[13].
> *a is a char [13] and gets converted to a char *.

I think I had a "minor" break-through in understanding here, thanks to
your help. It involves understanding the issue of "type" and realizing
how important it is ( wrt pointers) to "pointer arithmetic"...and that
is the part that I was missing.

This really clarifies the ability to access each "character" in a row
by using:

char *p;
p=a[1] or p=a[0]; etc etc

( Well, I hope it clarifies it...else it's back to the drawing
board!!!!).

Thanks very much for your help.

mdh, Aug 5, 2007
7. ### Joe WrightGuest

mdh wrote:
> <I should have included the original code...sorry. Included below.>
>
> May I ask two questions relating to this exercise? ( asking to repeat
> the example using pointers)
> Given a 2-dimensional array:
>
> char a[2][13] ( which is initialized in the exercise to represent
> days
> of the month in a leap/non-leap year)
>
> Part of the answer ( in Tondo and Gimpel) includes "assigning" a char
> pointer to the correct "row" thus:
>
> char *p
> p = a[leap]; ( with "leap" either 0 or 1);
>
> Question.
>
> If "a" is "converted" to a pointer to element 0 of row 1, then a[1]
> points p to element 0 of row 2? Is this the correct way of
> visualizing
> this?
>
> 2nd question involves pointer arithmetic.
> p is advanced using *++p.
> In order to calculate the difference between a[leap] and the current
> position of "p" the expression
>
> *pmonth = p - *(a + leap ) is used. ( again, "leap" is 0 or 1)
> ( *pmonth is a ptr of type integer declared as such in the parameter
> of the function)
>
> Question:
>
> I can see how p represents an address of the "pth" element of "a" and
> that this should simply be the difference between 2 pointers.
> However, the syntax
>
> *(a + leap) is the one that is confusing to me. I thought the "*" is
> the dereferencing operator, and as such, it should be (a + p) and
> not *(a+p).
>
> #include <stdio.h>
>
> static char daytab[2][13]={
> {0,31,28,31,30,31,30,31,31,31,30,31,30},
> {0,31,29,31,30,31,30,31,31,31,30,31,30}
> };
>
>

Thirty days hath September, April, June and November. All the rest have
31 save February which has 28 or 29.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---

Joe Wright, Aug 5, 2007
8. ### mdhGuest

>
> > static char daytab[2][13]={
> > {0,31,28,31,30,31,30,31,31,31,30,31,30},
> > {0,31,29,31,30,31,30,31,31,31,30,31,30}
> > };

>
> Thirty days hath September, April, June and November. All the rest have
> 31 save February which has 28 or 29.
>

oops...well...wasn't really the gist of the issue...but point taken.

mdh, Aug 5, 2007
9. ### Richard HeathfieldGuest

Joe Wright said:

> mdh wrote:
>> <I should have included the original code...sorry. Included below.>
>>
>> May I ask two questions relating to this exercise? ( asking to repeat
>> the example using pointers)
>> Given a 2-dimensional array:
>>
>> char a[2][13] ( which is initialized in the exercise to represent
>> days
>> of the month in a leap/non-leap year)
>>
>> Part of the answer ( in Tondo and Gimpel) includes "assigning" a char
>> pointer to the correct "row" thus:
>>
>> char *p
>> p = a[leap]; ( with "leap" either 0 or 1);
>>
>> Question.
>>
>> If "a" is "converted" to a pointer to element 0 of row 1, then a[1]
>> points p to element 0 of row 2? Is this the correct way of
>> visualizing
>> this?
>>
>> 2nd question involves pointer arithmetic.
>> p is advanced using *++p.
>> In order to calculate the difference between a[leap] and the current
>> position of "p" the expression
>>
>> *pmonth = p - *(a + leap ) is used. ( again, "leap" is 0 or 1)
>> ( *pmonth is a ptr of type integer declared as such in the parameter
>> of the function)
>>
>> Question:
>>
>> I can see how p represents an address of the "pth" element of "a" and
>> that this should simply be the difference between 2 pointers.
>> However, the syntax
>>
>> *(a + leap) is the one that is confusing to me. I thought the "*" is
>> the dereferencing operator, and as such, it should be (a + p) and
>> not *(a+p).
>>
>> #include <stdio.h>
>>
>> static char daytab[2][13]={
>> {0,31,28,31,30,31,30,31,31,31,30,31,30},
>> {0,31,29,31,30,31,30,31,31,31,30,31,30}
>> };
>>
>>

>
> Thirty days hath September, April, June and November. All the rest
> have 31

With you so far.

> save February which has 28 or 29.

No no no, it's:

"...Saving February alone,
Which hath 28 days clear,
And 29 in each leap year."

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999

Richard Heathfield, Aug 6, 2007
10. ### Keith ThompsonGuest

Richard Heathfield <> writes:
> Joe Wright said:

[...]
>> Thirty days hath September, April, June and November. All the rest
>> have 31

>
> With you so far.
>
>> save February which has 28 or 29.

>
> No no no, it's:
>
> "...Saving February alone,
> Which hath 28 days clear,
> And 29 in each leap year."

Thirty days hath September;
All the rest I don't remember.

Or maybe it's:

Thirty days hath September,
April, June, and November.
All the rest have thirty-one,
Save for February, which has none.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Aug 6, 2007
11. ### ¬a\\/bGuest

On Sun, 05 Aug 2007 12:06:24 -0400, Joe Wright wrote:

>Thirty days hath September, April, June and November. All the rest have
>31 save February which has 28 or 29.

trenta giorni a novembre
con april giugno e settembre,
di ventotto c'e' ne uno,
tutti gli altri son trentuno.

¬a\\/b, Aug 6, 2007
12. ### ¬a\\/bGuest

On Sun, 05 Aug 2007 13:01:57 +0200, Army1987 wrote:
>On Fri, 03 Aug 2007 09:32:54 -0700, mdh wrote:
>> Army1987 <> wrote:
>>>
>>> a is a char [2][13], which is converted to a char (* )[13].
>>> Thus a + 1 points to the second char [13] in the array, that is
>>> to the second row.
>>> a[1], that is *(a + 1), is a char [13], which is converted to
>>> a char * pointing to a[1][0]. Got it?

>>
>>
>> Yes...I think so. So, there are 2 "levels" of conversion?

>Depends on what you mean.
>a is a char [2][13] and gets converted to a char (*)[13].
>*a is a char [13] and gets converted to a char *.
>But the fact that you can write **a does NOT mean that a is ever
>converted to a char **. If an implementation had different sizes
>for pointers to pointers and pointers to arrays, sizeof(a + 0)
>would return the former. Also you could not assign a to a char **.
>**a works because it binds as *(*a), and *a has type char [13]
>before conversion and char * after conversion.
>Similarly, the fact that you can write
>#include <stdio.h>
>int main(void)
>{
> (
> *******
> * * *
> * * *
> * * *
> * * * * *
> * * *
> *******
> puts)("Peace!");
> return 0;
>}

your is the war symbol and not the peace symbols

if the above compile, the language is not well definite because if
"puts()" is an addreess *(char*)puts should be what the first byte of

(*puts)() should have to be tralslated in
mov eax, [puts]
call [eax]
and not in
call [puts]

if c define that in other way it appear to me wrong

>doesn't mean puts is ever converted to a 31th-level pointer to
>function returning int and taking a const char *.

3
3333333
3
3
3

¬a\\/b, Aug 6, 2007
13. ### Army1987Guest

On Mon, 06 Aug 2007 11:53:16 +0200, Â¬a\/b wrote:

> On Sun, 05 Aug 2007 13:01:57 +0200, Army1987 wrote:
>>On Fri, 03 Aug 2007 09:32:54 -0700, mdh wrote:
>>> Army1987 <> wrote:
>>>>
>>>> a is a char [2][13], which is converted to a char (* )[13].
>>>> Thus a + 1 points to the second char [13] in the array, that is
>>>> to the second row.
>>>> a[1], that is *(a + 1), is a char [13], which is converted to
>>>> a char * pointing to a[1][0]. Got it?
>>>
>>>
>>> Yes...I think so. So, there are 2 "levels" of conversion?

>>Depends on what you mean.
>>a is a char [2][13] and gets converted to a char (*)[13].
>>*a is a char [13] and gets converted to a char *.
>>But the fact that you can write **a does NOT mean that a is ever
>>converted to a char **. If an implementation had different sizes
>>for pointers to pointers and pointers to arrays, sizeof(a + 0)
>>would return the former. Also you could not assign a to a char **.
>>**a works because it binds as *(*a), and *a has type char [13]
>>before conversion and char * after conversion.
>>Similarly, the fact that you can write
>>#include <stdio.h>
>>int main(void)
>>{
>> (
>> *******
>> * * *
>> * * *
>> * * *
>> * * * * *
>> * * *
>> *******
>> puts)("Peace!");
>> return 0;
>>}

>
> your is the war symbol and not the peace symbols
>
> if the above compile, the language is not well definite because if
> "puts()" is an addreess *(char*)puts should be what the first byte of

No. Function pointers needn't work like object pointers.

> (*puts)() should have to be tralslated in
> mov eax, [puts]
> call [eax]
> and not in
> call [puts]

What is it translated into doesn't matter, as long as it does the
right thing, as per ISO/IEC 9899:1999 1p2 and 5.1.2.3. The "right
thing" the standard prescribes for puts("test") and
(*puts)("test") is the same [1], so they can (and should) be
translated into the same thing.

> if c define that in other way it appear to me wrong

puts has type function, so it is converted to a pointer to it
before operator * is applied to it.
puts, after conversion, has type pointer to function, so *puts has
type function, and it is converted to a pointer to it before
operator * is applied to it.
*puts after conversion has type pointer to function, so **puts has
type function, and it is converted to a pointer to it before
operator * is applied to it.

.... puts, after conversion, has type pointer
to function, so applying the function call postfix operator calls
the function it points to.

>>doesn't mean puts is ever converted to a 31th-level pointer to function
>>returning int and taking a const char *.

>
> 3
> 3333333
> 3
> 3
> 3

This is a syntax error in any context I can think of, except in a #if 0
group or equivalent.

[1] Except if puts is implemented as a macro.
--
Army1987 (Replace "NOSPAM" with "email")
"Never attribute to malice that which can be adequately explained
by stupidity." -- R. J. Hanlon (?)

Army1987, Aug 6, 2007
14. ### Ben BacarisseGuest

Re: Exercise 5-9 K&R -- NOW OFF TOPIC

Keith Thompson <> writes:

> Thirty days hath September;
> All the rest I don't remember.

This, for my brain, is an example of a mnemonic that is *harder* to
remember than the data it encodes. I use my knuckles (and the valleys
between them) -- you have to remember February, but that was never the
problem with the rhyme. It has the added advantage of making the
pattern crystal clear (alternation with a missing 30 between July and
August) which the rhyme completely obscures.

--
Ben.

Ben Bacarisse, Aug 6, 2007
15. ### RichardGuest

Re: Exercise 5-9 K&R -- NOW OFF TOPIC

Ben Bacarisse <> writes:

> Keith Thompson <> writes:
>
>> Thirty days hath September;
>> All the rest I don't remember.

>
> This, for my brain, is an example of a mnemonic that is *harder* to
> remember than the data it encodes. I use my knuckles (and the valleys
> between them) -- you have to remember February, but that was never the
> problem with the rhyme. It has the added advantage of making the
> pattern crystal clear (alternation with a missing 30 between July and
> August) which the rhyme completely obscures.

Just to be pedantic, your subject change (which then cancelled the
fact that I and maybe others had killed the thread as of "no interest")
was wrong. it was, by the definitions presented here, "Off Topic" long
index .... Bottom line? Don't change subject lines - especially when its
done to be pedantic in the first place since you're then guilty of
reawakening the thread for others who have no interest in it.

Richard, Aug 6, 2007
16. ### Army1987Guest

[OT] Re: Exercise 5-9 K&R

On Mon, 06 Aug 2007 13:07:24 +0100, Ben Bacarisse wrote:

> Keith Thompson <> writes:
>
>> Thirty days hath September;
>> All the rest I don't remember.

>
> This, for my brain, is an example of a mnemonic that is *harder* to
> remember than the data it encodes. I use my knuckles (and the valleys
> between them) -- you have to remember February, but that was never the
> problem with the rhyme. It has the added advantage of making the
> pattern crystal clear (alternation with a missing 30 between July and
> August) which the rhyme completely obscures.

An equivalent way is assigning each month to a musical note,
starting with January = F, February = F#, up to December = E while
imagining a piano keyboard. White keys correspond to months of 31
days and black keys correspond to months of 30 days or less.
--
Army1987 (Replace "NOSPAM" with "email")
"Never attribute to malice that which can be adequately explained
by stupidity." -- R. J. Hanlon (?)

Army1987, Aug 6, 2007
17. ### Joe WrightGuest

Richard Heathfield wrote:
> Joe Wright said:
>
>> mdh wrote:
>>> <I should have included the original code...sorry. Included below.>
>>>
>>> May I ask two questions relating to this exercise? ( asking to repeat
>>> the example using pointers)
>>> Given a 2-dimensional array:
>>>
>>> char a[2][13] ( which is initialized in the exercise to represent
>>> days
>>> of the month in a leap/non-leap year)
>>>
>>> Part of the answer ( in Tondo and Gimpel) includes "assigning" a char
>>> pointer to the correct "row" thus:
>>>
>>> char *p
>>> p = a[leap]; ( with "leap" either 0 or 1);
>>>
>>> Question.
>>>
>>> If "a" is "converted" to a pointer to element 0 of row 1, then a[1]
>>> points p to element 0 of row 2? Is this the correct way of
>>> visualizing
>>> this?
>>>
>>> 2nd question involves pointer arithmetic.
>>> p is advanced using *++p.
>>> In order to calculate the difference between a[leap] and the current
>>> position of "p" the expression
>>>
>>> *pmonth = p - *(a + leap ) is used. ( again, "leap" is 0 or 1)
>>> ( *pmonth is a ptr of type integer declared as such in the parameter
>>> of the function)
>>>
>>> Question:
>>>
>>> I can see how p represents an address of the "pth" element of "a" and
>>> that this should simply be the difference between 2 pointers.
>>> However, the syntax
>>>
>>> *(a + leap) is the one that is confusing to me. I thought the "*" is
>>> the dereferencing operator, and as such, it should be (a + p) and
>>> not *(a+p).
>>>
>>> #include <stdio.h>
>>>
>>> static char daytab[2][13]={
>>> {0,31,28,31,30,31,30,31,31,31,30,31,30},
>>> {0,31,29,31,30,31,30,31,31,31,30,31,30}
>>> };
>>>
>>>

>> Thirty days hath September, April, June and November. All the rest
>> have 31

>
> With you so far.
>
>> save February which has 28 or 29.

>
> No no no, it's:
>
> "...Saving February alone,
> Which hath 28 days clear,
> And 29 in each leap year."
>

Well thanks. You had to pull that up from somewhere. So it's only
short-term that's the problem?

As we get older, memory is the second thing to go. I forget what the
first was.. :=)

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---

Joe Wright, Aug 6, 2007