char a[SIZE]; // declares an char array of size SIZE
char *a; // declares a char pointer
// each of these declare an array of char pointers of size SIZE
char *a[SIZE];
char (*a[SIZE]);
char *(a[SIZE]);
ARE char *a[SIZE]; and char (*a[SIZE]); EQUIVALENT ?
Yes.
And we also say string a; is actually char *a;. So the later is a
pointer to a character , which when initialised stores address of char
a. So how it acts as a string?
Well, a string is just an array of chars that terminates with a the a '\0' (which is of course a char by itself).
Array elements are stored in contiguous places in memory. The address of an array (the whole memory block), whether that's a string or just a regular char array, is the same as the address of the first byte in the array which is also the same as the address of the first element in the array as well.
You may have now concluded how a variable of type char *
is capable of storing an address of a string. And the answer, to make that clear, is that the address of a string is the same as the address of the first char in the string and thus, it is an address of a char. Therefore, a variable of type char *
has no problem storing that.
Now the question is, if a char *
variable stores an address of a char, how does the computer know whether this char is part of a string/an array or just a single char. And the short answer is that the computer doesn't bother caring about that.
What should care about that is the code that uses this char *
variable. So if I have some function that expects an argument of type string (aka char *
) and the client code passed a pointer to a char that is not '\0', then the behavior of my function will be undefined. Here's a quick example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char dest[5];
char src = 'a';
strcpy(dest, &src); // NOTICE a pointer to a single char is passed
printf("%s\n", dest);
}
Output:
aP_m�
Isn't it just a variable storing address of a single character.
Similar to int *i. Which is a pointer to an integer not an array of
integers.
You should have learned now that a variable of a pointer type (let's call that T *
) in general can point to either a value of type T
or an array of T
values.
Update: answering your questions in the comment
While using int array[Size]; we have to allot the size in advance. And
while using int *array; we need not allocate the size..Is that true ?
Not really. When you declare an int array int array[size]
, you get size * 4 bytes (typically on most 32-bit systems) allocated for you automatically.
When using an int *
on the other hand, you may either set it to point to an address of already allocated piece of memory (whether this was allocated manually or automatically). For example:
int i = 10;
int *p = &i; // points to i
or you may allocate memory for it manually using a function like malloc
int p0 = malloc(sizeof (int)); // allocate memory for an int and point to it
If you chose the latter though, you'll need to manually free the memory that you've allocated manually.
If we are not allocating memory to the *array; pointer variable, how
can we say that it will allocate contiguous memory,as the next memory
address might be already occupied, as we have not reserved for the
array.
As the answer to the previous question shows, a pointer in general or an int pointer in particular does not point to anything initially (does not have memory allocated for it).
Here's another thing: the word contiguous does NOT mean that multiple calls to a function like malloc
allocate contiguous blocks in memory. It basically means that that each call allocates one block of the size provided as an argument. For example:
malloc(4 * sizeof (int));
allocates a block for 4 int values (or you could say for an array of 4 ints). These ints will live contiguously in memory.
It is not guaranteed that multiple calls to a function like malloc
will allocate contiguous blocks so you shouldn't consider that.