Let's start with a simple 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);
Another example: (source file)
#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: