Velocity Reviews > Exercise 5-9 K&R

# Exercise 5-9 K&R

mdh
Guest
Posts: n/a

 08-03-2007
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
Guest
Posts: n/a

 08-03-2007
<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;
}

Army1987
Guest
Posts: n/a

 08-03-2007
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 (?)

mdh
Guest
Posts: n/a

 08-03-2007

> 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 <(E-Mail Removed)> 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 (?)

Army1987
Guest
Posts: n/a

 08-05-2007
On Fri, 03 Aug 2007 09:32:54 -0700, mdh wrote:
> Army1987 <(E-Mail Removed)> 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 *.

mdh
Guest
Posts: n/a

 08-05-2007
On Aug 5, 4:01 am, Army1987 <(E-Mail Removed)> 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.

Joe Wright
Guest
Posts: n/a

 08-05-2007
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 ---

mdh
Guest
Posts: n/a

 08-05-2007

>
> > 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.

Richard Heathfield
Guest
Posts: n/a

 08-05-2007
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

Keith Thompson
Guest
Posts: n/a

 08-06-2007
Richard Heathfield <(E-Mail Removed)> 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.velocityreviews.com/forums/(E-Mail Removed) <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"