Re: The question regarding type of pointers



On Tue, 24 Apr 2012 21:05:38 -0700 (PDT), somenath
<somenathpal@xxxxxxxxx> wrote:

Hello All,

I am very confused about the output of the following program.

#include<stdio.h>
int daytab[2][13] = {
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31},
};
int day_of_year(int year,int month,int day)
{
int i;
int leap;
int (*p2)[13];
int (*p3)[2][13];
printf("\nsizeof daytab = %d\n", (int) sizeof(daytab));
printf("\nsizeof p3= %d\n", (int) sizeof(*p3));
printf("\nsizeof p3[2][3]= %d\n", (int) sizeof(p3[2][3]));
printf("\nsizeof p2= %d\n", (int) sizeof(*p2));

if (month <1 || month >12 || day <1|| day >31)
{
return -1;
}
leap = year %4 && year %100 !=0 || year %400;
p2 = &daytab[0];
p3 = &daytab;
printf("\nleap =%d\n",leap);
for (i =1 ;i<month;i++){
day += *(*(daytab+leap)+i);
//day += *(*(p2+leap)+i);
//day += *(*(*p3+leap)+i);

}

}

int main(void)
{
int day;
day = day_of_year(2012,3,3);
printf("\nDay = %d\n",day);
return 0;
}

Output of the program
sizeof daytab = 104

sizeof p3= 104

Obviously this is a lie since the call to printf did not print out the
size of p3 but the size of *p3. p3 is a pointer and in all likelihood
its size is either 4 or 8.


sizeof p3[2][3]= 52

sizeof p2= 52

A lie for the same reason.


leap =1

Day = 63

My question is how the below line getting evaluated and resulting
correct output?
day += *(*(daytab+leap)+i);

According to my understanding daytab is pointing to the whole daytab[2]
[13] array i.e it is equivalent to p3. So daytab +1 will point
beyond the daytab array so trying to de reference it will cause
undefined behaviour. But I am getting the right result. Where am I
going wrong?

As an object, daytab is indeed the complete array you describe. But
as an expression, daytab is converted to a pointer to the first
element of the array with type pointer to element type. (There are
exceptions which don't apply here; see 6.3.2.1-3 if interested.)

So daytab in this statement is identical to &daytab[0]. Therefore,
daytab points to the first array of 13 int. Since leap is 1,
daytab+leap points to the second array of 13 int. The expression
*(daytab+leap) dereferences this pointer value and evaluates to the
object daytab[1].

This object is also an array and is converted as described above.
Therefore, in this statement *(daytab+leap) is identical to
&daytab[1][0] which is the address of the first int in the second
array. Obviously *(daytab+leap)+i will point to the i-th int in this
array. The expression *(*(daytab+leap)+i) dereferences this address
to produce the value of the i-th int.

As others have pointed out, the calculation for leap is incorrect and
if you changed the year to 2013 it would produce a value as if that
year were a leap year also.


Along with this I would like to verify my understanding about the p2
and p3 as well.
So p2 point to the first row of the daytab array i.e it points to
{0,31,28,31,30,31,30,31,31,30,31,30,31},

p2 was never assigned a value so its value is indeterminate. You
could say it doesn't point anywhere currently. Since it is a pointer
to an array of 13 int, it could be made to point to the first "row"
(technically the first element) of daytab with either initialization
or assignment. Either daytab or &daytab[0] would serve as a suitable
expression to accomplish this.


Now p2+leap will point to second row depending upon the leap value.

p2+leap will point to the first or second row depending on whether
leap is 0 or 1, respectively.

*(p2+leap) is pointer to one of the element of the array for example

*(p2+leap) is the actual array (either first or second depending on
leap).

it may point to 0 of the first row. So adding i to it will shift the

As described above, the expression *(p2+leap) will be converted to a
pointer to the first element of the appropriate array determined by
leap. It will point to either daytab[0][0] or daytab[1][0], both of
which happen to be 0.

pointer in that row to the i th element. Then de-reference it result

p2 doesn't change value. The value of the expression will point to
the i-th element.

in the actual value.

Yes.


Similarly p3 will point to the whole array daytab. The type of *p3

Again, no value was assigned or initialized. p3 could point to daytab
but the only valid expression for achieving this is &daytab. Note the
difference between this and the possible expressions for p2 above.

will be equivalent to p2. So the pointer arithmetic on p3 behave same

The type of *p3 is array of 2 array of 13 int. The type of p2 is
pointer. They are not equivalent. (For example, the size of *p3 is
104 and the size of p2 is 4.)

as p2 . But I am not sure that i am right here as I get the out put

Pointer arithmetic on the two will NOT behave the same. p3+1 points
104 bytes beyond p3 while p2+1 points only 52 bytes beyond p2.

of
printf("\nsizeof p3= %d\n", (int) sizeof(*p3));

as same as
printf("\nsizeof daytab = %d\n", (int) sizeof(daytab));

p3 is a pointer to an array of 2 array of 13 int. Even though p3 has
not been assigned a value, the TYPE of *p3 is array of 2 array of 13
int. That is all the sizeof operator cares about. It does not
evaluate its operand. The operator is applied to the type of the
operand. daytab is an actual array of the same type and therefore has
the same size.


I am very much confused here.

Also i am not able to understand why the output of
printf("\nsizeof p3[2][3]= %d\n", (int) sizeof(p3[2][3])); is 52
which is same as

p3 is pointer to an array of 2 array of 13 int. Even though it
doesn't point to one, p3[0] is the "virtual object" it points to.
p3[1] would be the next object of this type in memory and p3[2] would
be the third such object. So p3[2] is an array of 2 array of 13 int.
Again, p3[2][0] is the first such array of 13 int it points to.
p3[2][1] would be the second, p3[2][2] the third, and p3[2][3] the
fourth. Therefore, p3[3][3] is an array of 13 int. Hence a total
size of 52.


printf("\nsizeof p2= %d\n", (int) sizeof(*p2));

p2 is a pointer to an array of 13 int. *p2 is the array it points to
(even if it doesn't really exist). Hence the same size.


I am not able correctly visualize the type of different pointers that
may be the reason for the whole confusion. Please provide some inputs
regarding this so that I can clearly understand the the pointer type.

I have read the article from the following link.
http://www.torek.net/torek/c/pa.html
After reading it i thought I have understood the different type
associated with pointer. But I am not able to understand still. It is
very much evident as I have failed to understand the behaviour of the
above program.

1 - Both the dereference operator (*) and the subscript operator ([]),
when applied to pointer, evaluate to a value that has the type of the
thing pointed to.

2 - Both operators, when applied to an array, evaluate to a value that
has the type of each of the array elements.

Thus, p3[0], which is by definition exactly the same as *p3, evaluates
to an array of 2 array of 13 int by 1 above. Similarly, *p2 evaluates
to an array of 13 int. And daytab[0] also evaluates to an array of 13
int by 2 above

Technically, sizeof does not evaluate its operand. It deals only with
the type that expression would have if it were evaluated.

--
Remove del for email
.



Relevant Pages

  • Re: Warning on assigning a function-returning-a-pointer-to-arrays
    ... This declares pfunc as a function taking no arguments and returning ... int x, y; ... Presumably pfuncwill return a pointer to a single int, ... or the first of a sequence of "array 5 of int"s. ...
    (comp.lang.c)
  • Re: How would you design Cs replacement?
    ... I would get rid of void. ... a member called size of type int. ... size of the array pointed at by v->dynamic is given by int size. ... If you pass an unsized pointer to a sized parameter, ...
    (comp.lang.c)
  • Re: Newbie
    ... to talk about the int value 3 and the int value 4, ... It also lets you talk about pointer ... C has a special rule for array objects. ... to printf() is: ...
    (comp.lang.c)
  • Re: union {unsigned char u[10]; ...}
    ... But character type is not a union. ... u.a is of type int. ... has to do so to make pointer equality work consistently). ... were a single-element array. ...
    (comp.lang.c)
  • The question regarding type of pointers
    ... int day_of_year ... According to my understanding daytab is pointing to the whole daytab ... array i.e it is equivalent to p3. ... pointer in that row to the i th element. ...
    (comp.lang.c)