{"id":7201,"date":"2025-10-18T00:01:00","date_gmt":"2025-10-18T07:01:00","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7201"},"modified":"2025-10-25T08:16:02","modified_gmt":"2025-10-25T15:16:02","slug":"adding-pointers-to-pointers","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7201","title":{"rendered":"Adding Pointers to Pointers"},"content":{"rendered":"<p>Expanding an allocated buffer is something you can do with a pointer, but not with an array. This flexibility is why I encourage all C language students to understand and use pointers, though it doesn&#8217;t make the concept nay less onery.<br \/>\n<!--more--><br \/>\nThe goal of the program from <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7192\">last week&#8217;s Lesson<\/a> is to build an array of allocated buffers, but it&#8217;s not an array. Instead, it&#8217;s an expanding buffer that contains pointers (memory locations) to integer storage. Each location holds the values to 10 integers. Figure 1 kinda illustrates how this contraption works.<\/p>\n<div id=\"attachment_7202\" style=\"width: 524px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-7202\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/10\/1018-figure1.png\" alt=\"Memory illustration\" width=\"514\" height=\"176\" class=\"size-full wp-image-7202\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/10\/1018-figure1.png 514w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/10\/1018-figure1-300x103.png 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/10\/1018-figure1-500x171.png 500w\" sizes=\"auto, (max-width: 514px) 100vw, 514px\" \/><p id=\"caption-attachment-7202\" class=\"wp-caption-text\">Figure 1. How storage is allocated and tracked in an expanding buffer.<\/p><\/div>\n<p>I call each allocated buffer of 10 integers is a &#8220;stick.&#8221; The program keeps creating new sticks, tracking their addresses which are held in storage referenced by pointer <code>tenint<\/code>. Each time a new stick of 10 integers is allocated, its address is stored, as illustrated in the figure.<\/p>\n<p>The program&#8217;s goal is to continue allocating new sticks for a total of ten. For today&#8217;s post, I improve the code from last week&#8217;s Lesson to show how ten such sticks can be allocated and tracked. No data is assigned to the sticks, as at this point my concern is managing the array of pointers.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2025_10_18-Lesson.c\" rel=\"noopener\" target=\"_blank\">2025_10_18-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;time.h&gt;\r\n\r\n<span class=\"comments\">\/* allocate storage for ten integers *\/<\/span>\r\nint *ten(void)\r\n{\r\n    int *iptr = NULL;\r\n\r\n    iptr = malloc( sizeof(int) * 10 );\r\n\r\n    return(iptr);\r\n}\r\n\r\nint main()\r\n{\r\n    int **tenint = NULL;\r\n    int y;\r\n\r\n    <span class=\"comments\">\/* seed the randomizer *\/<\/span>\r\n    srand( (unsigned)time(NULL) );\r\n\r\n    <span class=\"comments\">\/* allocate 10 sticks of 10 integers *\/<\/span>\r\n    for( y=0; y&lt;10; y++ )\r\n    {\r\n        <span class=\"comments\">\/* allocate first stick *\/<\/span>\r\n        if( tenint==NULL )\r\n        {\r\n            tenint = malloc( sizeof( int *) );\r\n            if( tenint==NULL )\r\n            {\r\n                fprintf(stderr,\"Unable to allocate storage\\n\");\r\n                exit(1);\r\n            }\r\n        }\r\n        else\r\n        <span class=\"comments\">\/* allocate additional sticks *\/<\/span>\r\n        {\r\n            tenint = realloc(tenint, sizeof( int *) * (y+1) );\r\n            if( tenint==NULL )\r\n            {\r\n                fprintf(stderr,\"Unable to reallocate storage\\n\");\r\n                exit(1);\r\n            }\r\n        }\r\n        <span class=\"comments\">\/* get the storage *\/<\/span>\r\n        *(tenint+y) = ten();\r\n        if( *(tenint+y)==NULL )\r\n        {\r\n            fprintf(stderr,\"Unable to allocate stick %d\\n\",y);\r\n            exit(1);\r\n        }\r\n        printf(\"Stick %d allocated\\n\",y);\r\n    }\r\n\r\n    <span class=\"comments\">\/* clean-up *\/<\/span>\r\n    for( y=0; y&lt;10; y++ )\r\n        free( *(tenint+y) );\r\n    free(tenint);\r\n    puts(\"All sticks freed\");\r\n    return 0;\r\n}<\/pre>\n<p>In the <em>main()<\/em> function, <em>int<\/em> pointer <code>tenint<\/code> is declared as a double-pointer:<\/p>\n<p><code>int **tenint = NULL;<\/code><\/p>\n<p>This variable stores the location where various addresses are stored. Let me explain:<\/p>\n<p>If the variable were declared as <code>*tenint<\/code>, it would reference the address of a buffer of integers, the location where integer values are stored. This variable was used in last week&#8217;s Lesson.<\/p>\n<p>Because the variable is declared as <code>**tenint<\/code>, it holds the address where addresses are stored, specifically the addresses of integer buffers. (Look at Figure 1 again.)<\/p>\n<p>In the code, the outer <em>for<\/em> loop uses variable <code>y<\/code> to allocate storage for the ten integer sticks. The first stick is handled differently as <code>tenint<\/code> isn&#8217;t yet allocated. An <em>if<\/em> test confirms this condition:<\/p>\n<p><code>if( tenint==NULL )<\/code><\/p>\n<p>If true, the <em>malloc()<\/em> function allocates storage for an integer pointer:<\/p>\n<p><code>tenint = malloc( sizeof( int *) );<\/code><\/p>\n<p>The <em>sizeof<\/em> operator uses expression <code>int *<\/code> to allocate storage for one integer pointer. This size is what&#8217;s needed, not storage for ten integers; what&#8217;s being stored is the <em>address<\/em> where ten integers are located in memory &mdash; a buffer.<\/p>\n<p>When <code>tenint<\/code> is already initialized, the <em>else<\/em> condition handles its expansion. The <em>realloc()<\/em> function adds one integer-pointer-sized chunk to the storage at <code>tenint<\/code>. Variable <code>y<\/code> is determines how large to expand the buffer based on how many integer pointers (addresses) are already present:<\/p>\n<p><code>tenint = realloc(tenint, sizeof( int *) * (y+1) );<\/code><\/p>\n<p>For each spin of the loop, the <code>tenint<\/code> buffer is enlarged by one <em>int<\/em>-pointer-sized chunk.<\/p>\n<p>Once new storage is allocated, an address is fetched from the <em>ten()<\/em> function. It&#8217;s assigned to the proper offset in the <code>tenint<\/code> buffer based on the value of variable <code>y<\/code>:<\/p>\n<p><code>*(tenint+y) = ten();<\/code><\/p>\n<p>The <code>*<\/code> (dereferencing) operator is used as it&#8217;s an address being stored in the buffer. This data type is what the <code>tenint<\/code> buffer is designed to store. If you instead use <code>tenint+y<\/code> (no asterisk), you get an address, not storage.<\/p>\n<p>No values are assigned to the allocated storage returned from the <em>ten()<\/em> function; I&#8217;ll add this code in next week&#8217;s Lesson. But the loop continues, storing the addresses of the allocated buffers at specific offsets in the <code>tenint<\/code> buffer. Ten sticks are allocated.<\/p>\n<p>For clean-up, each stick buffer is freed, then the <code>tenint<\/code> buffer:<\/p>\n<p><code>for( y=0; y&lt;10; y++ )<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;free( *(tenint+y) );<br \/>\nfree(tenint);<\/code><\/p>\n<p>Here&#8217;s a sample run:<\/p>\n<p><code>Stick 0 allocated<br \/>\nStick 1 allocated<br \/>\nStick 2 allocated<br \/>\nStick 3 allocated<br \/>\nStick 4 allocated<br \/>\nStick 5 allocated<br \/>\nStick 6 allocated<br \/>\nStick 7 allocated<br \/>\nStick 8 allocated<br \/>\nStick 9 allocated<br \/>\nAll sticks freed<\/code><\/p>\n<p>Key takeaways from this code are:<\/p>\n<ul>\n<li>The <code>tenint<\/code> list is a double pointer, the location of a buffer that stores addresses.<\/li>\n<li>Pointer math allows each address to be accessed by using this format: <code>*(tenint+y)<\/code><\/li>\n<li>Each allocated stick must be freed first, before freeing the <code>tenint<\/code> buffer.<\/li>\n<\/ul>\n<p>Crazy, but it works. For <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7209\">next week&#8217;s Lesson<\/a>, I plug values into each stick.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bloat that buffer to make room for more buffers! <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7201\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-7201","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7201"}],"version-history":[{"count":7,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7201\/revisions"}],"predecessor-version":[{"id":7224,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7201\/revisions\/7224"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}