Basics of Character Double Pointers
=====================================

In this section, you are going to learn

        .. panels::
                :container: container pb-4
                :column: col-lg-12 p-2
                :card: shadow

                How to use Double Pointers ?

        .. panels::
                :container: container pb-4
                :column: col-lg-12 p-2
                :card: shadow

		Basics of Double Pointers

		* :ref:`1 Double Pointer, 1 Single Pointer : Simple variables <basic_ptr_char_dp_sp_ex1>`
		* :ref:`1 Double Pointer, 1 Single Pointer : With Single pointer pointing to arrays <basic_ptr_char_dp_sp_ex2>`
		* :ref:`1 Double Pointer, 1 Single Pointer : With Single pointer heap allocation <basic_ptr_char_dp_sp_ex3>`
		* :ref:`1 Double Pointer : With two heap allocations : Create 1x1 array <basic_ptr_char_dp_sp_ex4>`
		* :ref:`1 Double Pointer : With two heap allocations : Create 1x10 array <basic_ptr_char_dp_sp_ex5>`
		* :ref:`1 Double Pointer : Pointing to array of single pointers : Static <basic_ptr_char_dp_sp_ex6>`
		* :ref:`1 Double Pointer : Pointing to array of single pointers : Dynamic <basic_ptr_char_dp_sp_ex7>`
		* :ref:`1 Double Pointer : Pass by Value : Wrong Usage <basic_ptr_char_dp_sp_ex8>`
		* :ref:`1 Double Pointer : Pass by Reference <basic_ptr_char_dp_sp_ex9>`

.. _basic_ptr_char_dp_sp_ex1:

.. tab-set::

        .. tab-item:: 1 Double Pointer, 1 Single Pointer : Simple variables

		* Step 1 : Define a character

		.. code-block:: c

			char c = 65;

		* Step 2 : Define a Single Pointer

		.. code-block:: c

		        char *sp = &c;

		OR

		.. code-block:: c

		        char *sp;

		        sp = &c;

		* Step 3 : Define a Double Pointer

		.. code-block:: c

		        char **dp = &sp;

		OR

		.. code-block:: c

		        char **dp;

		        dp = &sp;

		* Step 4 : Access user data (in this case character) using single pointer

		.. code-block:: c

		        printf("c = %d\n", *sp);

		* Step 5 : Access user data (in this case character) using double pointer

		.. code-block:: c

		        printf("c = %d\n", **dp);

		* Step 6 : Use ``*dp`` to point to new user data (in this case variable ``d``)

		.. code-block:: c

		       *dp = &d;

	        .. panels::
        	        :container: container pb-4
                	:column: col-lg-12 p-2
	                :card: shadow

			Remember below equations

			* dp = &sp
			* \*dp = sp
			* \*dp = &c
			* Hence changing ``*dp`` changes ``sp`` as well

		* Step 7 : Now user data can be accessed using \*sp, \*\*dp which prints value of character ``d``

		.. code-block:: c

		        printf("d = %d\n", d);
		        printf("d = %d\n", *sp);
		        printf("d = %d\n", **dp);

		* See full program below

		.. code-block:: c

			#include <stdio.h>

			int main(void)
			{
			        char c = 65;
			        char *sp = &c;
			        char **dp = &sp;

			        printf("c = %d\n", c); 
			        printf("*sp = %d\n", *sp);
			        printf("**dp = %d\n", **dp);

			        char d = 100;

			        *dp = &d;

			        printf("d = %d\n", d);
			        printf("*sp = %d\n", *sp);
			        printf("**dp = %d\n", **dp);

			        return 0;
			}

		* Output is as below

		.. code-block:: c

			c = 65
			*sp = 65
			**dp = 65

			d = 100
			*sp = 100
			**dp = 100

.. _basic_ptr_char_dp_sp_ex2:

.. tab-set::

        .. tab-item:: 1 Double Pointer, 1 Single Pointer : With Single pointer pointing to arrays

		* Step 1 : Define a single dimension array of characters

		.. code-block:: c

		        char arr[] = "Laptop";

		* Step 2 : Define a single pointer

		.. code-block:: c

			char *sp = arr;

		OR

		.. code-block:: c

			char *sp;

			sp = arr;

		OR

		.. code-block:: c

			char *sp;

			sp = &arr[0];

		* Step 3 : Define a double pointer

		.. code-block:: c

			char **dp = &sp;

		OR

		.. code-block:: c

			char **dp;

			dp = &sp;

		* Step 4 : Access user data (in this case array of characters) using single pointer variable ``sp``

		.. code-block:: c

		        printf("arr = %s\n", sp);

		* Step 5 : Access user data (in this case array of characters) using double pointer variable ``dp``

		.. code-block:: c

		        printf("arr = %s\n", *dp);

	        .. panels::
        	        :container: container pb-4
                	:column: col-lg-12 p-2
	                :card: shadow

        	        Note ``*dp`` should be called as single pointer because of below equations

			* dp = &sp;
			* \*dp = sp;

		* See full program below

		.. code-block:: c

			#include <stdio.h>

			int main(void)
			{
			        char arr[] = "Laptop";
			        char *sp = arr;
			        char **dp = &sp;

			        //Access full array
			        printf("arr = %s\n", arr);
			        printf("sp = %s\n", sp);
			        printf("*dp = %s\n", *dp);

			        //Access individual character
			        printf("arr[3] = %c\n", arr[3]);
			        printf("sp[3] = %c\n", sp[3]);
			        printf("(*dp)[3] = %c\n", (*dp)[3]);

			        return 0;
			}

		* Output is as below

		.. code-block:: c

			arr = Laptop
			sp = Laptop
			*dp = Laptop

			arr[3] = t
			sp[3] = t
			(*dp)[3] = t

.. _basic_ptr_char_dp_sp_ex3:

.. tab-set::

        .. tab-item:: 1 Double Pointer, 1 Single Pointer : With Single pointer heap allocation

		* Step 1 : Define a single pointer

		.. code-block:: c

			char *sp;

		* Step 2 : Allocate heap memory to single pointer

		.. code-block:: c

			sp = malloc(10 * sizeof(char));

		* Step 3 : Copy User data to heap memory

		.. code-block:: c

			strcpy(sp, "Laptop");

		* Step 4 : Define a double pointer

		.. code-block:: c

			char **dp;
			dp = &sp;

		* Step 5 : Access User data using single pointer variable ``sp``

		.. code-block:: c

			printf("arr = %s\n", sp);
			printf("arr[3] = %c\n", sp[3]);

		* Step 6 : Access User data using double pointer variable ``dp``

		.. code-block:: c

			printf("arr = %s\n", *dp);
			printf("arr[3] = %c\n", (*dp)[3]);

		* See full program below

		.. code-block:: c

			#include <stdio.h>
			#include <stdlib.h>
			#include <string.h>

			int main(void)
			{
			        char *sp;

			        sp = malloc(10 * sizeof(char));
			        strcpy(sp, "Laptop");

			        char **dp;
			        dp = &sp;

			        //Access full array
			        printf("arr = %s\n", sp);
			        printf("arr = %s\n", *dp);

			        //Access individual character
			        printf("arr[3] = %c\n", sp[3]);
			        printf("arr[3] = %c\n", (*dp)[3]);

				free(sp);

			        return 0;
			}

		* Output is as below

		.. code-block:: c

.. _basic_ptr_char_dp_sp_ex4:

.. tab-set::

        .. tab-item:: 1 Double Pointer : With two heap allocations : Create 1x1 array

		* Step 1 : Define a double pointer

		.. code-block:: c

			char **dp;

		* Step 2 : Allocate memory to a double pointer

		.. code-block:: c

			dp = malloc(sizeof(char *));

		* Step 3 : Allocate memory to a single pointer

		.. code-block:: c

			*dp = malloc(sizeof(char));

		* Step 4 : Store user data

		.. code-block:: c

			**dp = 65;

		* Step 5 : Read user data

		.. code-block:: c

			printf("User data = %d\n", **dp);

		* Step 6 : Free memory in opposite flow of allocation

		.. code-block:: c

			free(*dp);

			free(dp);

		* See full program below

		.. code-block:: c

			#include <stdio.h>
			#include <string.h>
			#include <stdlib.h>

			int main(void)
			{
			        char **dp;

			        dp = malloc(sizeof(char *));

			        *dp = malloc(sizeof(char));

			        **dp = 65;

			        printf("User data = %d\n", **dp);

			        free(*dp);

			        free(dp);

			        return 0;
			}

.. _basic_ptr_char_dp_sp_ex5:

.. tab-set::

        .. tab-item:: 1 Double Pointer : With two heap allocations : Create 1x10 array

		* Step 1 : Define a double pointer

		.. code-block:: c

			char **dp;

		* Step 2 : Allocate memory to a double pointer

		.. code-block:: c

			dp = malloc(sizeof(char *));

		* Step 3 : Allocate memory to a single pointer

		.. code-block:: c

			*dp = malloc(10 * sizeof(char));

		* Step 4 : Copy User data to heap

		.. code-block:: c

			strcpy(*dp, "Laptop");

		* Step 5 : Read user data from heap

		.. code-block:: c

			printf("User data = %s\n", *dp);

			for (int i = 0; i < 10; i++) {
				printf("User data = %c\n", (*dp)[i]);
			}

		* Step 6 : Free memory in opposite flow of allocation

		.. code-block:: c

			free(*dp);

			free(dp);

		* See full program below

		.. code-block:: c
	
			#include <stdio.h>
			#include <string.h>
			#include <stdlib.h>

			int main(void)
			{
			        char **dp;

			        dp = malloc(sizeof(char *));

			        *dp = malloc(10 * sizeof(char));
			        memset(*dp, 0, 10);

			        strcpy(*dp, "Laptop");

			        printf("User data = %s\n", *dp);

			        for (int i = 0; i < 10; i++) {
			                printf("User data = %c\n", (*dp)[i]);
			        }

			        free(*dp);

			        free(dp);

			        return 0;
			}

.. _basic_ptr_char_dp_sp_ex6:

.. tab-set::

        .. tab-item:: 1 Double Pointer : Pointing to array of single pointers : Static

		* Step 1 : Define 3 Single dimension character arrays

		.. code-block:: c

			char arr0[32] = "Laptop";
			char arr1[32] = "Mouse";
			char arr2[32] = "Keyboard";

		* Step 2 : Define array of single pointers

		.. code-block:: c

			char *sp_arr[] = {arr0, arr1, arr2};

		* Step 3 : Define a double pointer

		.. code-block:: c

			char **dp;

			dp = sp_arr;

		* Step 4 : Use ``dp`` to change contents of single dimension arrays

		.. code-block:: c

			strcpy(dp[0], "New Laptop");
			strcpy(dp[1], "New Mouse");
			strcpy(dp[2], "New Keyboard");

		* Step 5 : Use ``sp_arr`` to access contents of single dimension arrays

		.. code-block:: c

			printf("arr0 = %s\n", sp_arr[0]);
			printf("arr1 = %s\n", sp_arr[1]);
			printf("arr2 = %s\n", sp_arr[2]);

		* Step 6 : Use ``dp`` to access contents of single dimension arrays

		.. code-block:: c

			printf("arr0 = %s\n", dp[0]);
			printf("arr1 = %s\n", dp[1]);
			printf("arr2 = %s\n", dp[2]);

		* See full program below

		.. code-block:: c

			#include <stdio.h>
			#include <stdlib.h>
			#include <string.h>

			int main(void)
			{
			        char arr0[32] = "Laptop";
			        char arr1[32] = "Mouse";
			        char arr2[32] = "Keyboard";

			        char *sp_arr[] = {arr0, arr1, arr2};

			        char **dp;

			        dp = sp_arr;

			        strcpy(dp[0], "New Laptop");
			        strcpy(dp[1], "New Mouse");
			        strcpy(dp[2], "New Keyboard");

			        printf("arr0 = %s\n", sp_arr[0]);
			        printf("arr0 = %s\n", dp[0]);

			        printf("arr1 = %s\n", sp_arr[1]);
			        printf("arr1 = %s\n", dp[1]);

			        printf("arr2 = %s\n", sp_arr[2]);
			        printf("arr2 = %s\n", dp[2]);

			        return 0;
			}

.. _basic_ptr_char_dp_sp_ex7:

.. tab-set::

        .. tab-item:: 1 Double Pointer : Pointing to array of single pointers : Dynamic

		* Step 1 : Define a double pointer

		.. code-block:: c

			char **dp;

		* Step 2 : Allocate heap memory : Create 3 single pointers ``dp[0]``, ``dp[1]``, ``dp[2]``

		.. code-block:: c

			dp = malloc(3 * sizeof(char *));

		* Step 3 : Allocate heap memory : Create 3 single dimension character arrays of size 32 characters each

		.. code-block:: c

			dp[0] = malloc(32 * sizeof(char));
			dp[1] = malloc(32 * sizeof(char));
			dp[2] = malloc(32 * sizeof(char));

		* Step 4 : Store user data

		.. code-block:: c

			strcpy(dp[0], "New Laptop");
			strcpy(dp[1], "New Mouse");
			strcpy(dp[2], "New Keyboard");

		* Step 5 : Access user data

		.. code-block:: c

			printf("string 0 = %s\n", dp[0]);
			printf("string 1 = %s\n", dp[1]);
			printf("string 2 = %s\n", dp[2]);

		* Step 6 : Free 3 character arrays

		.. code-block:: c

			free(dp[0]);
			free(dp[1]);
			free(dp[2]);

		* Step 7 : Free 3 single pointers

		.. code-block:: c

			free(dp);

		* See full program below

		.. code-block:: c

			#include <stdio.h>
			#include <stdlib.h>
			#include <string.h>

			int main(void)
			{
			        char **dp;

			        dp = malloc(3 * sizeof(char *));
			        dp[0] = malloc(32 * sizeof(char));
			        dp[1] = malloc(32 * sizeof(char));
			        dp[2] = malloc(32 * sizeof(char));

			        strcpy(dp[0], "New Laptop");
			        strcpy(dp[1], "New Mouse");
			        strcpy(dp[2], "New Keyboard");

			        printf("string 0 = %s\n", dp[0]);
			        printf("string 1 = %s\n", dp[1]);
			        printf("string 2 = %s\n", dp[2]);

			        free(dp[0]);
			        free(dp[1]);
			        free(dp[2]);

			        free(dp);

			        return 0;
			}

.. _basic_ptr_char_dp_sp_ex8:

.. tab-set::

        .. tab-item:: 1 Double Pointer : Pass by Value : Wrong usage

		* In this example,

			* Programmer is defining a function called ``fun`` which takes care of allocation 
			* Plans to use the allocated memory in function ``main``
			* But pointer ``dp`` is passed by value to function ``fun``
				* Which means there are two pointers, ``dp`` and ``dp_v``
				* Any assignement done to ``dp_v`` will not affect ``dp`` in caller
			* Hence, below program crashes inside function ``main`` when first ``strcpy`` is tried

		* See full program below

		.. code-block:: c

			#include <stdio.h>
			#include <stdlib.h>
			#include <string.h>

			void fun(char **dp_v)
			{
			        dp_v = malloc(3 * sizeof(char *));
			        dp_v[0] = malloc(32 * sizeof(char));
			        dp_v[1] = malloc(32 * sizeof(char));
			        dp_v[2] = malloc(32 * sizeof(char));
			}

			int main(void)
			{
			        char **dp;

			        fun(dp);

			        strcpy(dp[0], "New Laptop");
			        strcpy(dp[1], "New Mouse");
			        strcpy(dp[2], "New Keyboard");

			        printf("dp[0] = %s\n", dp[0]);
			        printf("dp[1] = %s\n", dp[1]);
			        printf("dp[2] = %s\n", dp[2]);

			        free(dp[0]);
			        free(dp[1]);
			        free(dp[2]);

			        free(dp);

			        return 0;
			}

.. _basic_ptr_char_dp_sp_ex9:

.. tab-set::

        .. tab-item:: 1 Double Pointer : Pass by Reference

		* In order to fix the problem mentioned in above case, let us pass double pointer by reference

		* Step 1 : Define a double pointer

		.. code-block:: c

			char **dp;

		* Step 2 : Pass double pointer by reference

		.. code-block:: c

			fun(&dp);

		* Step 3 : Allocate memory inside function ``fun``

		.. code-block:: c

			void fun(char ***dp_r)
			{
			        *dp_r = malloc(3 * sizeof(char *));
			        (*dp_r)[0] = malloc(32 * sizeof(char));
			        (*dp_r)[1] = malloc(32 * sizeof(char));
			        (*dp_r)[2] = malloc(32 * sizeof(char));
			}

		* Step 4 : Use single pointers dp[0], dp[1], dp[2] in caller to store user data

		.. code-block:: c

			strcpy(dp[0], "New Laptop");
			strcpy(dp[1], "New Mouse");
			strcpy(dp[2], "New Keyboard");

		* Step 5 : Use single pointers dp[0], dp[1], dp[2] in caller to access user data

		.. code-block:: c

			printf("dp[0] = %s\n", dp[0]);
			printf("dp[1] = %s\n", dp[1]);
			printf("dp[2] = %s\n", dp[2]);

		* Step 6 : Free 3 arrays of characters after use

		.. code-block:: c

			free(dp[0]);
			free(dp[1]);
			free(dp[2]);

		* Step 7 : Free 3 Single pointers after use

		.. code-block:: c

			free(dp);

		* See full program below

		.. code-block:: c

			#include <stdio.h>
			#include <stdlib.h>
			#include <string.h>

			void fun(char ***dp_r)
			{
			        *dp_r = malloc(3 * sizeof(char *));
			        (*dp_r)[0] = malloc(32 * sizeof(char));
			        (*dp_r)[1] = malloc(32 * sizeof(char));
			        (*dp_r)[2] = malloc(32 * sizeof(char));
			}

			int main(void)
			{
			        char **dp;

			        fun(&dp);

			        strcpy(dp[0], "New Laptop");
			        strcpy(dp[1], "New Mouse");
			        strcpy(dp[2], "New Keyboard");

			        printf("dp[0] = %s\n", dp[0]);
			        printf("dp[1] = %s\n", dp[1]);
			        printf("dp[2] = %s\n", dp[2]);

			        free(dp[0]);
			        free(dp[1]);
			        free(dp[2]);

			        free(dp);

			        return 0;
			}

.. card:: See Also

        * Current Module

                * :doc:`../basic_ptr`

        * Previous Module

                * :doc:`../../variable_and_ptr/variable_and_ptr`

        * Next Module

                * :doc:`../../array_n_ptrs/array_n_ptrs`

        * Other Modules

                * :doc:`../../malloc_ptr/malloc_ptr`
                * :doc:`../../typecasting_n_ptr/typecasting_n_ptr`
                * :doc:`../../funcs_n_ptrs/funcs_n_ptrs`
                * :doc:`../../memcpy_ptr/memcpy_ptr`
                * :doc:`../../const_ptr/const_ptr`
                * :doc:`../../void_ptr/void_ptr`
                * :doc:`../../array_of_ptr/array_of_ptr`
                * :doc:`../../ptr_to_array/ptr_to_array`
                * :doc:`../../function_ptr/function_ptr`
                * :doc:`../../pre_incr_ptr/pre_incr_ptr`
                * :doc:`../../post_incr_ptr/post_incr_ptr`
                * :doc:`../../pre_decr_ptr/pre_decr_ptr`
                * :doc:`../../post_decr_ptr/post_decr_ptr`