Let's start with a simple example:
(source file)
Another example:
(source file)
#include <stdio.h>
int main ()
{
// Declare a pointer to an int.
int *p;
// Get the space from malloc:
p = (int*) malloc (sizeof(int));
// Assign a value and print:
*p = 5;
printf ("Int value: %d\n", *p);
// Free the memory when done:
free (p);
}
Note:
// Declare a pointer to an int.
int *p;
simply declares the pointer variable. The pointer may itself is
invalid since it hasn't been assigned a value yet.
#include <stdio.h>
int main ()
{
// Declare a pointer to an int.
int *p;
printf ("Initial value of pointer: %lu\n", p); // Prints 0 (C99)
}
Thus, the "picture" after declaration is:
#include <stdio.h>
int main ()
{
int *p;
int i;
// Extract the address of i and put that in p:
p = &i;
}
#include <stdio.h>
int main ()
{
int *p;
// Get the space from malloc:
p = (int*) malloc (sizeof(int));
}
*p = 5;
printf ("Int value: %d\n", *p);
After this assignment, the picture is:
#include <stdio.h>
int main ()
{
int *p;
p = (int*) malloc (4);
*p = 5;
printf ("Int value: %d\n", *p);
}
This works if we happen to know that an int takes up
4 bytes.
#include <stdio.h>
int main ()
{
int *p;
p = (int*) malloc (16);
*p = 5;
printf ("Int value: %d\n", *p);
}
Here, 16 contiguous bytes are allocated, of which only 4 are used.
printf ("The number of bytes needed by an integer: %d\n", sizeof(int));
printf ("The number of bytes needed by a double: %d\n", sizeof(double));
p = (int*) malloc (sizeof(int));
An easy way to remember this is: "the cast type is the same as
the argument
to sizeof but with a *
appended".
#include <stdio.h>
int main ()
{
// Declare a pointer to an int.
int *p;
// Print the initial value of the pointer:
printf ("Initial value of pointer: %lu\n", p); // Prints 0 (C99)
// Get the space from malloc:
p = (int*) malloc (sizeof(int));
// Print the address of the memory block returned by malloc:
printf ("Current pointer: %lu\n", p);
}
// Free the memory when done:
free (p);
#include <stdio.h>
int main ()
{
double *doublePtr;
char *charPtr;
printf ("The number of bytes needed by a double: %d\n", sizeof(double));
printf ("The number of bytes needed by a char: %d\n", sizeof(char));
// Get the space from malloc:
doublePtr = (double*) malloc (sizeof(double));
charPtr = (char*) malloc (sizeof(char));
// Print the address of the memory block returned by malloc:
printf ("double pointer is at location: %lu\n", doublePtr);
printf ("char pointer is at location: %lu\n", charPtr);
// Assign values and print:
*doublePtr = 3.141;
*charPtr = 'A';
printf ("double value = %lf char value = %c\n", *doublePtr, *charPtr);
// Free the memory when done:
free (doublePtr);
free (charPtr);
}
Note:
doublePtr = (double*) malloc (sizeof(double));
charPtr = (char*) malloc (sizeof(char));
An example using arrays:
(source file)
#include <stdio.h>
int main ()
{
int A[10];
int *B;
printf ("BEFORE malloc: Address A=%lu Address B=%lu\n", A, B);
// Prints an address for A, but zero for B
// Assign space to B:
B = (int*) malloc (sizeof(int) * 10);
printf ("AFTER malloc: Address A=%lu Address B=%lu\n", A, B);
// Prints an address for A and newly allocated address for B.
// Two ways of assigning values:
A[3] = 5;
*(A + 4) = 6;
printf ("A[3]=%d A[4]=%d\n", A[3], A[4]); // Prints 5 and 6.
// Two ways of assigning values:
B[3] = 7;
*(B + 4) = 8;
printf ("B[3]=%d B[4]=%d\n", B[3], B[4]); // Prints 7 and 8.
// Done.
free (B);
}
Note:
A[3] = 5; *(A + 4) = 6; // Fifth position in array A.
*(A + 4) = 6;assigns the value 6 into this location.
Next, let's consider 2D arrays:
(source file)
#include <stdio.h>
int main ()
{
double A[10][10]; // Static allocation of space to array A.
double **B; // We'll use malloc to assign space to B.
int i;
printf ("BEFORE malloc: Address A=%lu Address B=%lu\n", A, B);
// Prints an address for A, but zero for B
// Assign space for first dimension of B (an array of pointers-to-double)
B = (double**) malloc (10 * sizeof(double*));
for (i=0; i<10; i++) {
B[i] = (double*) malloc (10 * sizeof(double));
}
printf ("AFTER malloc: Address A=%lu Address B=%lu\n", A, B);
// Prints an address for A and newly allocated address for B.
// Two ways of assigning values:
A[3][4] = 5.55;
*((double*)A + 5*10 + 6) = 6.66;
printf ("A[3][4]=%lf A[5][6]=%lf\n", A[3][4], A[5][6]); // Prints 5.55 and 6.66.
// Twy ways of assigning values:
B[3][4] = 7.77;
*((*(B + 5)) + 6) = 8.88;
printf ("B[3][4]=%lf B[5][6]=%lf\n", B[3][4], B[5][6]); // Prints 7.77 and 8.88
// Free the individual small arrays:
for (i=0; i<10; i++) {
free (B[i]);
}
// Free the array of double-pointers:
free (B);
}
Note:
A[3][4] = 5.55; B[3][4] = 7.77;
*((double*)A + 5*10 + 6) = 6.66; *((*(B + 5)) + 6) = 8.88;
*((double*)A + 5*10 + 6) = 6.66;
*((*(B + 5)) + 6) = 8.88;
An example using struct's and pointers:
(source file)
#include <stdio.h>
int main ()
{
// A list node:
struct ListNode {
char *name; // Fields: name and age.
int age;
struct ListNode *next; // The "next" pointer.
};
struct ListNode *front; // Point to front of list.
struct ListNode *rear; // To rear.
struct ListNode *tempPtr; // For temporary use.
// Create a first node:
tempPtr = (struct ListNode *) malloc (sizeof(struct ListNode));
tempPtr->name = "Alice";
tempPtr->age = 19;
tempPtr->next = NULL;
// Add to list:
front = rear = tempPtr;
// Create a second node:
tempPtr = (struct ListNode *) malloc (sizeof(struct ListNode));
tempPtr->name = "Bob";
tempPtr->age = 18;
tempPtr->next = NULL;
// Add to list.
front->next = tempPtr;
rear = tempPtr;
// Print etc ...
}
Note: