{"id":5168,"date":"2022-01-29T00:01:05","date_gmt":"2022-01-29T08:01:05","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5168"},"modified":"2022-01-22T10:30:32","modified_gmt":"2022-01-22T18:30:32","slug":"oops-a-not-really-3d-array","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5168","title":{"rendered":"Oops: A (Not Really) 3D Array"},"content":{"rendered":"<p>I screwed up some code in a most delightful manner, all without knowing what I did. In fact, it was a student who ran my less-than-brilliant code and discovered the obvious flaw. But I was clueless.<br \/>\n<!--more--><br \/>\nThe code in question demonstrates a three dimensional array simulating three tic-tac-toe game boards. The 3D array is initialized, each value filled with the period character. Then each game board is output one after the other in a fancy way.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2022_01_29-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2022_01_29-Lesson-a.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n    char tictactoe[3][3][3];\r\n    int x,y,z;\r\n\r\n    <span class=\"comments\">\/* initialize *\/<\/span>\r\n    for(x=0;x&lt;3;x++)\r\n        for(y=0;y&lt;3;y++)\r\n            for(z=0;z&lt;3;z++)\r\n                tictactoe[x][y][z] = '.';\r\n\r\n    <span class=\"comments\">\/* display *\/<\/span>\r\n    puts(\"Tic Tac Toe\");\r\n    for(x=0;x&lt;3;x++)\r\n    {\r\n        printf(\"%*c\",x+1,' ');\r\n        for(y=0;y&lt;3;y++)\r\n        {\r\n            for(z=0;z&lt;3;z++)\r\n                printf(\" %c \",tictactoe[x][y][z]);\r\n            printf(\"     \");    <span class=\"comments\">\/* 5 spaces *\/<\/span>\r\n        }\r\n        putchar('\\n');\r\n    }\r\n\r\n    return(0);\r\n}<\/pre>\n<p>Array <code>tictactoe[][][]<\/code> is declared at Line 5. A triple nested <em>for<\/em> loop initializes each element in the 3D array to the period character at Line 12: <code>tictactoe[x][y][z] = '.';<\/code><\/p>\n<p>Starting at Line 15, the array is output, again using a triple nested <em>for<\/em> loop and various devious <em>printf()<\/em> statements. Here is the output:<\/p>\n<p><code>Tic Tac Toe<br \/>\n&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.<br \/>\n&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.<\/code><\/p>\n<p>So far, so good. But I wanted to drive home the point that the array is stored internally as one-dimensional, and that the multidimensional notation is for the programmer&#8217;s benefit.<\/p>\n<p>In my not-so-brilliant efforts at demonstration, I modified the code. First to change the array definition to one dimension:<\/p>\n<p><code>char tictactoe[27];<\/code><\/p>\n<p>Then second, I changed the array&#8217;s reference in the initialization. Here is where I screwed up:<\/p>\n<p><code>tictactoe[x+y+z] = '.';<\/code><\/p>\n<p>And finally, I repeated the mistake in the output statement:<\/p>\n<p><code>printf(\" %c \",tictactoe[x+y+z]);<\/code><\/p>\n<p>The full source code for this flawed program is <a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2022_01_29-Lesson-b.c\" rel=\"noopener\" target=\"_blank\">available on GitHub<\/a>, if you really want to barf.<\/p>\n<p>The problem is that the element offsets are calculated cumulatively. Wrong. The proper math is to multiply them by their offset values: 9, 3, and 1. Unfortunately, this goof isn&#8217;t apparent in the output, which looks the same as before:<\/p>\n<p><code>Tic Tac Toe<br \/>\n&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.<br \/>\n&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.<\/code><\/p>\n<p>Internally, however, the <code>tictactoe[]<\/code> array is only partially initialized: <code>x+y+x<\/code> at its maximum value is only six: 2+2+2. The rest of the array contains garbage, which isn&#8217;t output despite the fancy formatting.<\/p>\n<p>To prove that the code is flawed, I added an initial loop to set all values in the array to periods. Then I used my flawed loop, <code>tictactoe[x+y+x]<\/code>, to set hyphens in the array. Finally, I wrote the correct calculation in the output statement, so that I could see the entire improperly initialized array:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2022_01_29-Lesson-c.c\" rel=\"noopener\" target=\"_blank\">2022_01_29-Lesson-c.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n    char tictactoe[27];\r\n    int x,y,z;\r\n\r\n    <span class=\"comments\">\/* initialize *\/<\/span>\r\n    for(x=0; x&lt;27; x++ )\r\n        tictactoe[x] = '.';\r\n\r\n    for(x=0;x&lt;3;x++)\r\n        for(y=0;y&lt;3;y++)\r\n            for(z=0;z&lt;3;z++)\r\n                tictactoe[x+y+z] = '-';\r\n\r\n    <span class=\"comments\">\/* display *\/<\/span>\r\n    puts(\"Tic Tac Toe\");\r\n    for(x=0;x&lt;3;x++)\r\n    {\r\n        printf(\"%*c\",x+1,' ');\r\n        for(y=0;y&lt;3;y++)\r\n        {\r\n            for(z=0;z&lt;3;z++)\r\n                printf(\" %c \",tictactoe[x*9+y*3+z]);\r\n            printf(\"     \");    <span class=\"comments\">\/* 5 spaces *\/<\/span>\r\n        }\r\n        putchar('\\n');\r\n    }\r\n\r\n    return(0);\r\n}<\/pre>\n<p>At Line 25, you see the proper math required to access each element in the array:<\/p>\n<p><code>tictactoe[x*9+y*3+z]<\/code><\/p>\n<p>As the output loop, variable <code>x<\/code> must be multiplied by nine to get the offset correct. Then variable <code>y<\/code> is multiplied by three to account for the 3&#215;3 grid in a tic-tac-toe game. Variable <code>z<\/code> is unchanged. Here is the revealing output:<\/p>\n<p><code>Tic Tac Toe<br \/>\n&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp;.&nbsp;&nbsp;.<br \/>\n&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;.&nbsp;&nbsp;.<\/code><\/p>\n<p>In the flawed code, only the first seven elements are initialized with <code>[x+y+z]<\/code>. The range is from zero through six. The rest of the array isn&#8217;t touched in the original, flawed code. This issue went unnoticed because my mistake was repeated in both the initialization and the output loops.<\/p>\n<p>I call this mistake a lazy one. I&#8217;ve initialized 3D arrays before, but somehow my brain farted and I used <code>[x+y+z]<\/code> instead of <code>[x*9+y*3+z]<\/code>. Silly me. Lesson learned.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes I mess up and have no idea that I&#8217;ve messed up. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5168\">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-5168","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\/5168","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=5168"}],"version-history":[{"count":10,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5168\/revisions"}],"predecessor-version":[{"id":5182,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5168\/revisions\/5182"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5168"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5168"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}