{"id":6528,"date":"2024-08-17T00:01:49","date_gmt":"2024-08-17T07:01:49","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=6528"},"modified":"2024-08-24T09:56:33","modified_gmt":"2024-08-24T16:56:33","slug":"the-art-of-memory-reallocation","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=6528","title":{"rendered":"The Art of Memory Reallocation"},"content":{"rendered":"<p>Clearing the pointer hurdle is a major leap to learning the C programming language. Using the <em>malloc()<\/em> function to allocate storage is central to grasping this concept. Then along comes the <em>realloc()<\/em> function, and minds are blown.<br \/>\n<!--more--><br \/>\nThe <em>realloc()<\/em> function swallows an existing pointer, one that&#8217;s been allocated a chunk of storage, and it resizes the memory chunk. The new size can be larger. The new size can be smaller.<\/p>\n<p>To demonstrate this function, the following code allocates a 2K buffer to hold a short string. This buffer is then reallocated to fit the string snuggly.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2024_08_17-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2024_08_17-Lesson-a.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;string.h&gt;\r\n\r\nint main()\r\n{\r\n    char string[] = \"Hello there!\";\r\n    char *sp;\r\n\r\n    printf(\"Original string: %s\\n\",string);\r\n\r\n    <span class=\"comments\">\/* allocate way too much storage *\/<\/span>\r\n    sp = malloc(2048);\r\n    if( sp==NULL )\r\n    {\r\n        fprintf(stderr,\"Failed to allocate way too much storage\\n\");\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* copy the string into storage *\/<\/span>\r\n    strcpy(sp,string);\r\n    printf(\"String copied: '%s'\\n\",sp);\r\n\r\n    <span class=\"comments\">\/* reallocate (re-size) the storage *\/<\/span>\r\n    sp = realloc(sp,strlen(string)+1);\r\n    if( sp==NULL )\r\n    {\r\n        fprintf(stderr,\"Failed to reallocate storage\\n\");\r\n        exit(1);\r\n    }\r\n    printf(\"Storage reallocated: '%s'\\n\",sp);\r\n\r\n    <span class=\"comments\">\/* clean up *\/<\/span>\r\n    free(sp);\r\n    return(0);\r\n}<\/pre>\n<p>The <em>malloc()<\/em> function allocates a 2048 byte buffer, into which the existing string is copied. The string sits small in this nice, roomy buffer.<\/p>\n<p>Then along comes the <em>realloc()<\/em> function, which re-sizes the allocated buffer to exactly the size of the string, plus the null character: <code>sp = realloc(sp,strlen(string)+1);<\/code> The same pointer is used for the reallocation; no need to create a new buffer. <\/p>\n<p>Here&#8217;s the output:<\/p>\n<p><code>Original string: Hello there!<br \/>\nString copied: 'Hello there!'<br \/>\nStorage reallocated: 'Hello there!'<\/code><\/p>\n<p>All this activity may seem unnecessary to save about 2K of storage for a modern computer with gigabytes of RAM. Back in the day, however, re-sizing an input buffer was something that programmers were compelled to do. Even so, re-sizing buffers is possible, probably more often to make the buffer larger than to make it smaller. In fact, for graphics programming, I&#8217;m always increasing buffers as an image is read or manipulated.<\/p>\n<p>When a buffer is made larger, the new memory is uninitialized &mdash; is which is what you should expect if you work with storage in C. A question that looms is what happens when the reallocated buffer is smaller than the original? Let&#8217;s find out!<\/p>\n<p>The following code modifies the original, but the reallocated buffer is only six bytes in size:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2024_08_17-Lesson-b.c\" rel=\"noopener\" target=\"_blank\">2024_08_17-Lesson-b.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;string.h&gt;\r\n\r\nint main()\r\n{\r\n    char string[] = \"Hello there!\";\r\n    char *sp;\r\n\r\n    printf(\"Original string: %s\\n\",string);\r\n\r\n    <span class=\"comments\">\/* allocate way too much storage *\/<\/span>\r\n    sp = malloc(2048);\r\n    if( sp==NULL )\r\n    {\r\n        fprintf(stderr,\"Failed to allocate way too much storage\\n\");\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* copy the string into storage *\/<\/span>\r\n    strcpy(sp,string);\r\n    printf(\"String copied: '%s'\\n\",sp);\r\n\r\n    <span class=\"comments\">\/* reallocate (re-size) the storage *\/<\/span>\r\n    sp = realloc(sp,6);\r\n    if( sp==NULL )\r\n    {\r\n        fprintf(stderr,\"Failed to reallocate storage\\n\");\r\n        exit(1);\r\n    }\r\n    <span class=\"comments\">\/* cap the string *\/<\/span>\r\n    *(sp+5) = '\\0';\r\n    printf(\"Storage reallocated: '%s'\\n\",sp);\r\n\r\n    <span class=\"comments\">\/* clean up *\/<\/span>\r\n    free(sp);\r\n    return(0);\r\n}<\/pre>\n<p>In this update, the <em>realloc()<\/em> function&#8217;s size is set to six bytes: <code>sp = realloc(sp,6);<\/code> The remainder of the buffer, which contains the full original string plus up to 2K of garbage, is lopped off like the green part of a carrot. What&#8217;s left in the reallocated buffer are just the first six characters, &#8220;Hello &#8221; (plus the space).<\/p>\n<p>To make the buffer a string, I poke in the null character to replace the space: <code>*(sp+5) = '\\0';<\/code><\/p>\n<p>Here&#8217;s the updated output:<\/p>\n<p><code>Original string: Hello there!<br \/>\nString copied: 'Hello there!'<br \/>\nStorage reallocated: 'Hello'<\/code><\/p>\n<p>In <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6534\">next week&#8217;s Lesson<\/a>, I dive deep into the <em>realloc()<\/em> function, exploring what it does behind the scenes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Please, Mr. Computer, change the size of this memory chunk. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6528\">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-6528","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\/6528","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=6528"}],"version-history":[{"count":4,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6528\/revisions"}],"predecessor-version":[{"id":6549,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6528\/revisions\/6549"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6528"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6528"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6528"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}