{"id":6867,"date":"2025-03-15T00:01:41","date_gmt":"2025-03-15T07:01:41","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=6867"},"modified":"2025-03-08T13:45:40","modified_gmt":"2025-03-08T21:45:40","slug":"a-problem-with-strings-in-two-dimensional-arrays","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=6867","title":{"rendered":"A Problem with Strings in Two-Dimensional Arrays"},"content":{"rendered":"<p>Declaring an array of strings as a pointer has many advantages, as demonstrated in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6859\">last week&#8217;s Lesson<\/a>. Above all, I like that I don&#8217;t have to calculate the longest string&#8217;s length to set the size for the second dimension. But what happens when set this size incorrectly?<br \/>\n<!--more--><br \/>\nHere is how I prefer to set an array of strings:<\/p>\n<p><code>char *a[] = { \"alfa\", \"bravo\", \"charlie\",<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;\"delta\", \"echo\", \"foxtrot\", \"golf\",<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;\"hotel\"<br \/>\n};<\/code><\/p>\n<p>Internally, each string is allocated its own chunk of memory. The array is composed of a series of pointers which reference where each string dwells in memory. Figure 1 illustrates how this works by using debugging information from the program:<\/p>\n<div id=\"attachment_6868\" style=\"width: 560px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-6868\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/03\/0315-figure1.png\" alt=\"Memory locations and their contents, strings.\" width=\"550\" height=\"299\" class=\"size-full wp-image-6868\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/03\/0315-figure1.png 550w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/03\/0315-figure1-300x163.png 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/03\/0315-figure1-500x272.png 500w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><p id=\"caption-attachment-6868\" class=\"wp-caption-text\">Figure 1. How an array of strings maps out by using pointers (addresses) that reference each string in memory.<\/p><\/div>\n<p>Here is a hexdump of the data stored in memory, which shows another perspective on how the data is packed:<\/p>\n<p><code>00000000&nbsp;&nbsp;61&nbsp;6c&nbsp;66&nbsp;61&nbsp;00&nbsp;62&nbsp;72&nbsp;61&nbsp;&nbsp;76&nbsp;6f&nbsp;00&nbsp;63&nbsp;68&nbsp;61&nbsp;72&nbsp;6c&nbsp;&nbsp;|alfa.bravo.charl|<br \/>\n00000010&nbsp;&nbsp;69&nbsp;65&nbsp;00&nbsp;64&nbsp;65&nbsp;6c&nbsp;74&nbsp;61&nbsp;&nbsp;00&nbsp;65&nbsp;63&nbsp;68&nbsp;6f&nbsp;00&nbsp;66&nbsp;6f&nbsp;&nbsp;|ie.delta.echo.fo|<br \/>\n00000020&nbsp;&nbsp;78&nbsp;74&nbsp;72&nbsp;6f&nbsp;74&nbsp;00&nbsp;67&nbsp;6f&nbsp;&nbsp;6c&nbsp;66&nbsp;00&nbsp;68&nbsp;6f&nbsp;74&nbsp;65&nbsp;6c&nbsp;&nbsp;|xtrot.golf.hotel|<br \/>\n00000030&nbsp;&nbsp;00&nbsp;20&nbsp;25&nbsp;73&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;01&nbsp;1b&nbsp;03&nbsp;3b&nbsp;28&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;|.&nbsp;%s.......;(...|<\/code><\/p>\n<p>Note how each string is stored one after the other, the null byte carefully separating each?<\/p>\n<p>Now consider this array:<\/p>\n<p><code>char a[8][8] = { \"alfa\", \"bravo\", \"charlie\",<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;\"delta\", \"echo\", \"foxtrot\", \"golf\",<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;\"hotel\"<br \/>\n};<\/code><\/p>\n<p>Array <code>a[][]<\/code> is composed of a grid of 64 characters. It contains eight strings, each allocated 8 characters for each string. Figure 2 illustrates how this data squats in memory.<\/p>\n<div id=\"attachment_6870\" style=\"width: 560px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-6870\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/03\/0315-figure2.png\" alt=\"memory locations and strings\" width=\"550\" height=\"291\" class=\"size-full wp-image-6870\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/03\/0315-figure2.png 550w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/03\/0315-figure2-300x159.png 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/03\/0315-figure2-500x265.png 500w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><p id=\"caption-attachment-6870\" class=\"wp-caption-text\">Figure 2. How a two-dimensional array stores the eight strings.<\/p><\/div>\n<p>From Figure 2, you see wasted space. Fourteen bytes are unused in the grid, which doesn&#8217;t seem like much but it&#8217;s close to 20 percent of storage. For larger data stored in this manner, a lot of memory is wasted. Here is how the memory dump looks:<\/p>\n<p><code>00000000&nbsp;&nbsp;61&nbsp;6c&nbsp;70&nbsp;68&nbsp;61&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;62&nbsp;72&nbsp;61&nbsp;76&nbsp;6f&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;|alpha...bravo...|<br \/>\n00000010&nbsp;&nbsp;63&nbsp;68&nbsp;61&nbsp;72&nbsp;6c&nbsp;69&nbsp;65&nbsp;00&nbsp;&nbsp;64&nbsp;65&nbsp;6c&nbsp;74&nbsp;61&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;|charlie.delta...|<br \/>\n00000020&nbsp;&nbsp;65&nbsp;63&nbsp;68&nbsp;6f&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;66&nbsp;6f&nbsp;78&nbsp;74&nbsp;72&nbsp;6f&nbsp;74&nbsp;00&nbsp;&nbsp;|echo....foxtrot.|<br \/>\n00000030&nbsp;&nbsp;67&nbsp;6f&nbsp;6c&nbsp;66&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;68&nbsp;6f&nbsp;74&nbsp;65&nbsp;6c&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;|golf....hotel...|<\/code><\/p>\n<p>The following is code that outputs the two-dimensional array&#8217;s data:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2025_03_15-Lesson.c\" rel=\"noopener\" target=\"_blank\">2025_03_15-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n    char a[8][8] = { \"alpha\", \"bravo\", \"charlie\",\r\n        \"delta\", \"echo\", \"foxtrot\", \"golf\",\r\n        \"hotel\"\r\n    };\r\n    int x;\r\n\r\n    for( x=0; x&lt;8; x++ )\r\n        puts(a[x]);\r\n\r\n    return 0;\r\n}<\/pre>\n<p>The output is predictably boring:<\/p>\n<p><code>alpha<br \/>\nbravo<br \/>\ncharlie<br \/>\ndelta<br \/>\necho<br \/>\nfoxtrot<br \/>\ngolf<br \/>\nhotel<\/code><\/p>\n<p>What happens when the second dimension is set to 7 instead of 8? Yes, the program builds without any warnings or errors. But the gird is too tight to hold the null characters after strings <code>charlie<\/code> and <code>foxtrot<\/code>. Here&#8217;s the updated output:<\/p>\n<p><code>alpha<br \/>\nbravo<br \/>\ncharliedelta<br \/>\ndelta<br \/>\necho<br \/>\nfoxtrotgolf<br \/>\ngolf<br \/>\nhotel<\/code><\/p>\n<p>Eight strings are output, as each string is still referenced by its starting character in elements <code>a[0][0]<\/code> through <code>a[7][0]<\/code>. Because the null character after the longest strings is clobbered in memory, you see bad data output in the form of <code>charliedelta<\/code> and <code>foxtrotgolf<\/code>. A hexdump of memory shows how tightly and improperly the data is packed:<\/p>\n<p><code>00000000&nbsp;&nbsp;61&nbsp;6c&nbsp;70&nbsp;68&nbsp;61&nbsp;00&nbsp;00&nbsp;62&nbsp;&nbsp;72&nbsp;61&nbsp;76&nbsp;6f&nbsp;00&nbsp;00&nbsp;63&nbsp;68&nbsp;&nbsp;|alpha..bravo..ch|<br \/>\n00000010&nbsp;&nbsp;61&nbsp;72&nbsp;6c&nbsp;69&nbsp;65&nbsp;64&nbsp;65&nbsp;6c&nbsp;&nbsp;74&nbsp;61&nbsp;00&nbsp;00&nbsp;65&nbsp;63&nbsp;68&nbsp;6f&nbsp;&nbsp;|arliedelta..echo|<br \/>\n00000020&nbsp;&nbsp;00&nbsp;00&nbsp;00&nbsp;66&nbsp;6f&nbsp;78&nbsp;74&nbsp;72&nbsp;&nbsp;6f&nbsp;74&nbsp;67&nbsp;6f&nbsp;6c&nbsp;66&nbsp;00&nbsp;00&nbsp;&nbsp;|...foxtrotgolf..|<br \/>\n00000030&nbsp;&nbsp;00&nbsp;68&nbsp;6f&nbsp;74&nbsp;65&nbsp;6c&nbsp;00&nbsp;00&nbsp;&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;|.hotel..........|<\/code><\/p>\n<p>All this information just reinforces why I prefer to use an array of pointers to store strings as opposed to a two-dimensional array. You&#8217;re free to use both, but I find the limitations and awkwardness of dealing with a two-dimensional array to outweigh any negative consequences of using pointers.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Two dimensional arrays of strings can get messy! <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6867\">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-6867","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\/6867","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=6867"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6867\/revisions"}],"predecessor-version":[{"id":6877,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6867\/revisions\/6877"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6867"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6867"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6867"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}