Exercise 5-9 K&R

M

mdh

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

thanks in advance.
 
M

mdh

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

thanks in advance.#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;
}
 
A

Army1987

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

mdh

mdh said:
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 said:
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"?

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

BTW...great quote !
 
A

Army1987

Army1987 said:
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 *.
 
M

mdh

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

Joe Wright

mdh said:
<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).

thanks in advance.
#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.
 
M

mdh

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

Richard Heathfield

Joe Wright said:
mdh said:
<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).

thanks in advance.
#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."
 
K

Keith Thompson

Richard Heathfield said:
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.
 
¬

¬a\\/b

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

Army1987 said:
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
that address has in

(*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

Army1987

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
that address has in
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.
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.
 
B

Ben Bacarisse

Keith Thompson said:
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.
 
R

Richard

Ben Bacarisse said:
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
before your reply which bought the off topic post back into my thread
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.
 
A

Army1987

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

Joe Wright

Richard said:
Joe Wright said:
mdh said:
<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).

thanks in advance.
#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.. :=)
 

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

Similar Threads

C exercise 1
POWERSHELL-BATCHFILE EXERCISE 2
Excercise 5-9 (K&R II) 10
K&N Exercise Problem 2
K&R exercise 5-5 10
clc-wiki answer to K+R exercise 2-7 6
K&R2, exercise 5-4, strend(s,t) 15
K&R2, exercise 4-2 12

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top