Pointer specification and deferencing traditionally cause more problems for programmers in C than anything else. The following is a short summary of their usage which, whilst not complete, should be sufficient to reduce the debugging strategy of arbitrarily inserting /removing & or * in the code and thinking positive thoughts.
Declaring Pointer Variables.
In a variable declaration, * means that the variable is a
(starting) address.
Hence type1* A defines a variable to store an address.
Addresses don't have types, so why the type1? The most likely
reason you would want to know an address is so you can do something
with the data at that address, and it is usually necessary to
know the type of the data you are operating on.
Hence type1* A declares a starting address for data of
type type1.
If you really don't care about the type of the data you can use
void* A
Note that you never use an & in variable declarations.
Using pointers to pass parameters
Why would you want to specify an address?
The most common reasons for using pointers is in passing data as a
parameter to a function and the data is
myFunction1(type1 X);
myFunction2(type1* Y);
main()
{
type1 A;
type1 *B;
myFunction1(A);
myFunction2(B);
In the first case, a copy of A (however large) is made and
placed on the stack before myFunction1 is called.
The calling program reserves some space for data
of type1 and passes the address for myFunction to fill it in.
We need an operator to tell us the address of any variable -
hence the &
type1 A; /* reserve space of type1 */
calledFunction(&A); /* tell myFunction where it is */
The called function will receive an address so its definition
must have the form
calledFunction(type1 *anAddress)
The called program has reserved the space for the data
(perhaps via a malloc() call or a static declaration), fills it in and
tells the calling program where to find it. The calling program only has
to reserve enough space for this address
type 1 *A; /* reserve 4 bytes for an address */
A = calledFunction(); /* here it is */
The called function will return an address so its
definition must have the form
type1 *calledFunction()
Examples of Parameter Passing
int A;
char B;
scanf("%d:%c\n", &A,&B);
If the input line was 1234:b then A would contain the
integer 1234 and B the character b
struct stat inode;
char path[255];
int status;
status = stat(path,&inode);
DIR *directory;
char path[255];
directory = opendir(path);
De-referencing Pointers
Pointers are typically used to pass addresses to or return addresses
from functions. So how do we access the data that to which these
addresses relate?
Consider the case where the calling function reserves the space.
'calling function' myFunction(type1 *B)
type1 variableA;
myFunction(&variableA); *B = xxxxxxx
If the data is a simple type (e.g. int, char etc.)
/* pointers.c - */
main(int argc, char **argv)
{
int i,j;
char* string;
printf("\t\t\tMemory Location/Type\n");
printf("Name\t\t\tchar**\tchar*\tchar\t\tValue\n\n");
printf("argv \t\t\t%d \t\t\t%d \n",&argv, argv);
for (i=0;i<argc;i++)
{
printf(" argv[%d] \t\t\t%d \t\t%d \n",i,&argv[i],argv[i]);
for (j=0;*(argv[i]+j)!=0;j++)
{
printf("\t argv[%d][%d] \t\t\t%d \t%c \n",i,j,&argv[i][j],argv[i][j]);
}
printf("\t *(argv[%d]+%d) \t\t\t%d \tNULL \n",i,j,argv[i]+j);
}
printf("\n\nNOTE FROM THE ABOVE THAT\n\n");
printf("1. If a variable NAME is of type XXX**, then it represents a list of addresses\n");
printf(" and its value is the address of the head, %d , of the list\n\n",argv);
printf("2. Each element of the list is of type XXX* and represents a list of XXX's\n");
printf(" and the ith element is the address of the start, %d for i=0,of \n",argv[0]);
printf(" list NAME[i]. Since each element is a pointer, it is %d bytes long\n\n",sizeof(char*));
printf("3. Each element of NAME[i] is of type XXX and of length %d byte(s)\n",sizeof(char));
printf(" It can be referred to as NAME[i][j] or as *(NAME[i]+j) i.e. the value of \n");
printf(" the element located j*sizeof(XXX) bytes from the start of NAME[i] e.g.\n");
printf(" argv[0][1] located at %d with value %c is the same as\n",&argv[0][1],argv[0][1]);
printf(" *(argv[0]+1) located at %d with value %c \n\n\n",argv[0]+1,*(argv[0]+1));
}