confused with sizeof and pointers

V

vijay

Hello,

I am new to C Programming and just started reading K&R. I was about to
finish the pointers chapter but got very confused with:

1. int arr[10];
From what I have read, arr is a pointer to the first int and &arr is a
pointer to the whole array of 10 ints. Then why does sizeof(arr) gives
40 while sizeof(&arr) gives 4. Shouldn't is be the other way around.

2. int arr[2][2]={{1,2},{3,4}};
printf("%u %u",arr,*arr);

produces the same output(base address). But haven't we dereferenced arr
in the second case. I mean, arr is an address to the base of the array
and putting a star in front of should give us the value there.

regards,
vijay.
 
E

Eric Sosman

vijay said:
Hello,

I am new to C Programming and just started reading K&R. I was about to
finish the pointers chapter but got very confused with:

1. int arr[10];
From what I have read, arr is a pointer to the first int and &arr is a
pointer to the whole array of 10 ints. Then why does sizeof(arr) gives
40 while sizeof(&arr) gives 4. Shouldn't is be the other way around.

2. int arr[2][2]={{1,2},{3,4}};
printf("%u %u",arr,*arr);

produces the same output(base address). But haven't we dereferenced arr
in the second case. I mean, arr is an address to the base of the array
and putting a star in front of should give us the value there.

Section 6 of the comp.lang.c Frequently Asked
Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html

may help you understand this better. Read it, and
post again if you are still confused.
 
M

Mark Odell

vijay said:
Hello,

I am new to C Programming and just started reading K&R. I was about to
finish the pointers chapter but got very confused with:

1. int arr[10];
From what I have read, arr is a pointer to the first int and &arr is a
pointer to the whole array of 10 ints.

No, arr and &arr are equivalent. One is a pointer to the first element
of arr[0] and the other is an expression that results in a pointer to
the first element of arr[0]. At least that's how I think of it.
Then why does sizeof(arr) gives
40 while sizeof(&arr) gives 4. Shouldn't is be the other way around.

Answered above, since sizeof arr (no parens need for objects) is the
size of the entire array, you get 40 on your system. Since &arr is an
expression for a pointer to the first element of arr, you should get the
size of a pointer, not the array.
2. int arr[2][2]={{1,2},{3,4}};
printf("%u %u",arr,*arr);

produces the same output(base address). But haven't we dereferenced arr
in the second case. I mean, arr is an address to the base of the array
and putting a star in front of should give us the value there.

Both arr and *arr are pointers, arr is a pointer to a pointer to int and
*arr is a pointer to int. They should be the same in this case since
they both point to arr[0][0]. You should also use this syntax for pointers:

printf("%p %p\n", (void *) arr, (void *) *arr);

- Mark
 
E

Eric Sosman

Mark said:
vijay said:
Hello,

I am new to C Programming and just started reading K&R. I was about to
finish the pointers chapter but got very confused with:

1. int arr[10];
From what I have read, arr is a pointer to the first int and &arr is a
pointer to the whole array of 10 ints.


No, arr and &arr are equivalent. One is a pointer to the first element
of arr[0] and the other is an expression that results in a pointer to
the first element of arr[0]. At least that's how I think of it.

Perhaps you should adjust your thinking by pondering
Question 6.12 in the comp.lang.c Frequently Asked Questions
(FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html
[Remainder of Mark's post snipped; it indicates that he
is just as confused as is Vijay.]
 
K

Keith Thompson

vijay said:
I am new to C Programming and just started reading K&R. I was about to
finish the pointers chapter but got very confused with:

1. int arr[10];

From what I have read, arr is a pointer to the first int and &arr is a
pointer to the whole array of 10 ints. Then why does sizeof(arr) gives
40 while sizeof(&arr) gives 4. Shouldn't is be the other way around.

The C FAQ is at <http://www.eskimo.com/~scs/C-faq/faq.html>. Read
section 6, "Arrays and Pointers".

Briefly, when an array name appears in an expression, it's usually,
but not always, converted to a pointer to its first element. When it
appears as the operand of a unary "&" or sizeof operator, this
conversion doesn't happen. That's why "sizeof(arr)" (or "sizeof arr";
the parentheses aren't necessary) gives you the size of the whole
array, not the size of a pointer, and "&arr" gives you a pointer to
the whole array (which is like a pointer to its first element except
for the type).
2. int arr[2][2]={{1,2},{3,4}};
printf("%u %u",arr,*arr);

produces the same output(base address). But haven't we dereferenced arr
in the second case. I mean, arr is an address to the base of the array
and putting a star in front of should give us the value there.

Here you're invoking undefined behavior by calling printf() with a
"%u" format, but not passing a value of type unsigned int. It may
happen to work on your system (if unsigned ints and pointers happen to
be passed as arguments the same way), but it's not guaranteed. To
print a pointer value, use the "%p" format. Since "%p" expects a
void*, you need to convert the argument explicitly (there's no
implicit conversion in this case).

So try this:

int arr[2][2]={{1,2},{3,4}};
printf("%p %p\n", (void*)arr, (void*)*arr);

arr is of type array[2] of array[2] of int.

For the second argument to printf(), arr decays to a pointer to an
array[2] of int; converting to void* gives you a pointer usable with
"%p".

For the third argument, arr again decays to a pointer to an array[2]
of int. Applying the "*" operator gives you an array[2] of int, which
then decays to a pointer to int. (I think that's right; if not,
someone will jump in and correct me.) It points to the same memory
location as the second argument, but with a different type.

So the second argument points to arr[2], an array of 2 ints, and the
third argument points to arr[2][2], an int. Both are at the same
address.

Here's a program that might demonstrate more clearly what's going on,
using a function that expects arguments of the appropriate types:

#include <stdio.h>

static void print_values(int (*arg1)[2], int *arg2)
{
printf("%p %p\n", (void*)arg1, (void*)arg2);
}

int main(void)
{
int arr[2][2]={{1,2},{3,4}};
printf("%p %p\n", (void*)arr, (void*)*arr);
print_values(arr, *arr);
return 0;
}
 
K

Keith Thompson

Mark Odell said:
No, arr and &arr are equivalent. One is a pointer to the first element
of arr[0] and the other is an expression that results in a pointer to
the first element of arr[0]. At least that's how I think of it.

Correction: a pointer to the first element of arr, not to the first
element of arr[0].

[...]
Both arr and *arr are pointers, arr is a pointer to a pointer to int
and *arr is a pointer to int. They should be the same in this case
since they both point to arr[0][0]. You should also use this syntax
for pointers:

arr is an array, not a pointer; it's implicitly converted to a pointer
when used in an expression (in most contexts).

There is no pointer-to-pointer-to-int here. What arr decays to (i.e.,
is implicitly converted to) is a pointer to an array, not a pointer to
a pointer.
printf("%p %p\n", (void *) arr, (void *) *arr);

Yes.
 
A

Ajoy K Thamattoor

Nope. Their types are different. For most implementations,
their actual values are likely to be the same, but there are no
guarantees.
One is a pointer to the first element
of arr[0] and the other is an expression that results in a pointer to
the first element of arr[0]. At least that's how I think of it.


Correction: a pointer to the first element of arr, not to the first
element of arr[0].

A legal standalone 'arr' is equivalent to &arr[0] except when it
is the operand of a sizeof. Both are of type (type_of_arr_element *)
and point to the first element of 'arr'.
&arr has type
(pointer to array of type same as 'arr'). It points to the beginning of
the array 'arr'.
The actual rules are more subtle - in particular when used
as function arguments, 'arr' doesn't decay to a pointer, it gets
adjusted to be a pointer. In practice, the above info suffices.
 
D

Dave Thompson

On Thu, 17 Mar 2005 16:59:57 -0800, Ajoy K Thamattoor
Nope. Their types are different. For most implementations,
their actual values are likely to be the same, but there are no
guarantees.
Exceedingly likely; there are no guarantees, but AFAIK we in c.l.c
know of no exceptions. (We _do_ know of exceptions to the also
unguaranteed assumption that all data pointers, or even all pointers,
are the same.)
One is a pointer to the first element
of arr[0] and the other is an expression that results in a pointer to
the first element of arr[0]. At least that's how I think of it.


Correction: a pointer to the first element of arr, not to the first
element of arr[0].
arr evaluates to a pointer to the first element of arr, that is the
row arr[0]. &arr evaluates to a pointer to the whole array, not the
first element or any other, although as above in practice the whole
array is at the same address as its first element(s).
A legal standalone 'arr' is equivalent to &arr[0] except when it
is the operand of a sizeof. Both are of type (type_of_arr_element *)
and point to the first element of 'arr'.
Right.

&arr has type
(pointer to array of type same as 'arr'). It points to the beginning of
the array 'arr'.

Almost right; it points to the whole array, which as above in practice
is at the same address.
The actual rules are more subtle - in particular when used
as function arguments, 'arr' doesn't decay to a pointer, it gets
adjusted to be a pointer. In practice, the above info suffices.

Use as function (actual) argument isn't different; it decays just like
any expression. You may be thinking of the _declaration_ of function
(dummy) _parameters_ where a parameter declared as array of T is
adjusted to pointer to T -- and is therefore the correct type to
receive an argument which was an array that decayed to pointer to
element. (And similarly a parameter declared as a function type is
adjusted to a pointer to that function type.)

- David.Thompson1 at worldnet.att.net
 
E

Eric Sosman

Dave said:
Exceedingly likely; there are no guarantees, but AFAIK we in c.l.c
know of no exceptions. (We _do_ know of exceptions to the also
unguaranteed assumption that all data pointers, or even all pointers,
are the same.)

We also know of C implementations where `arr + 1' and
`&arr + 1' are not at all alike -- namely, every single C
implementation imaginable ...
 
P

pete

Dave said:
On Thu, 17 Mar 2005 16:59:57 -0800, Ajoy K Thamattoor

Exceedingly likely; there are no guarantees,

Wrong. There is a guarantee.
((char *)arr == (char *)&arr)
is guaranteed true when arr is an array.

Is 0 equal to 0u?
Their types are different and the comparison can't be done
without a conversion of the int type expression to unsigned.
 

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

No members online now.

Forum statistics

Threads
474,161
Messages
2,570,892
Members
47,427
Latest member
HildredDic

Latest Threads

Top