Declaring type of pointers?
Type-safety. If you don't know what p
is supposed to point to, then there'd be nothing to prevent category errors like
*p = "Nonsense";
int i = *p;
Static type checking is a very powerful tool for preventing all kinds of errors like that.
C and C++ also support pointer arithmetic, which only works if the size of the target type is known.
address occupies same amount of memory whatever my be the type
That's true for today's popular platforms. But there have been platforms for which that wasn't the case. For example, a pointer to a multi-byte word could be smaller than a pointer to a single byte, since it doesn't need to represent the byte's offset within the word.
Because:
- addresses to different types don't need to have the same size. The standard explicitly specifies so (C 2011 standard (online draft), 6.2.5/28).
- type-safety: this allows the compiler to detect when you provide an incompatible pointer to a function, or in an assignment. This in turn prevents ugly situations where you mess up the argument order to a function.
- the compiler needs to know the type when the pointer is dereferenced.
- to do pointer arithmetic the size of the object pointed to needs to be known and thus its type.
The last two points don't apply to void
pointers, which is why they cannot by dereferenced and no pointer arithmetic may be done on them. The standard specifies that a void
pointer must be big enough to hold any kind of pointer (except function pointers, which are a different story altogether) and that assignment to and from void
pointers may be made without casts (at least in C, in C++ casts are always needed).
One reason is in pointer arithmetic. You cannot do p+1
unless you know the size of the element to which p
points -- that is the size of the type to which p
is a pointer. If you'd try p+1
on a void *p
you're likely to get a bad answer (it is the same as if done on a char *
but maybe you didn't want that; it is caught by -pedantic
as a warning and by -pedantic-errors
as an error).
Another reason is type safety. If a function receives as argument an int *
you cannot pass a pointer to char
(a string) there. You'd get a warning (an error with -Werror
/ -pedantic-errors
). Consider this (dummy) code:
void test(int *x)
{
}
int main()
{
char *x = "xyz";
test(x);
return 0;
}
Compiling (using gcc (GCC) 4.8.2 20131017 (Red Hat 4.8.2-1)
) gives:
1.c: In function ‘main’:
1.c:8:2: warning: passing argument 1 of ‘test’ from incompatible pointer type [enabled by default]
test(x);
^
1.c:1:6: note: expected ‘int *’ but argument is of type ‘char *’
void test(int *x)
^
So, why do we need to declare its type?
You want to know the type of the pointer so you can do static type checking.
We also need to know the type in order for pointer arithmetic to work, for example when we index into an array(which is equivalent to pointer arithmetic) of different size types the pointer will be adjusted by a type dependent amount. If we look at the draft C99 standard section 6.5.6
Additive operators says (emphasis mine):
For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type [...]
So the pointer needs to be an object type, which means not incomplete or void.
You also said:
address occupies same amount of memory whatever may be the type. So, why do we need to declare its type?
This is not always true in C++ the size of pointers to member functions can change depending on the class type, one of the good articles that covers this is Pointers to member functions are very strange animals.
Furthermore we can see that both the C99 draft standard section section 6.2.5
Types paragraph 27 which says:
[...] Pointers to other types need not have the same representation or alignment requirements.
and the draft C++ standard section 3.9.2
Compound types paragraph 3 says:
[...] The value representation of pointer types is implementation-defined. Pointers to cv-qualified and cv-unqualified versions (3.9.3) of layout-compatible types shall have the same value representation and alignment requirements (3.11). [...]
do not require pointers to have the same representation except in specific cases.
You need to specify the type as the standard demands so. Moreover, so that there are no issues when you try to perform pointer arithmetic like addition or subtraction.