{"id":132,"date":"2011-02-04T22:27:57","date_gmt":"2011-02-04T21:27:57","guid":{"rendered":"http:\/\/trigonakis.com\/blog\/?p=132"},"modified":"2011-07-20T16:03:07","modified_gmt":"2011-07-20T15:03:07","slug":"pointers-and-arrays-in-c","status":"publish","type":"post","link":"http:\/\/trigonakis.com\/blog\/2011\/02\/04\/pointers-and-arrays-in-c\/","title":{"rendered":"Pointers and Arrays in C"},"content":{"rendered":"<p>As anyone who had programmed in C knows, pointers can be (also) used to access the data of an array.<\/p>\n<p>From the Wikipedia article about C language:<\/p>\n<blockquote>\n<p>C supports the use of pointers, a very simple type of reference that records, in effect, the address or location of an object or function in memory. Pointers can be dereferenced to access data stored at the address pointed to, or to invoke a pointed-to function. Pointers can be manipulated using assignment and also pointer arithmetic. The run-time representation of a pointer value is typically a raw memory address (perhaps augmented by an offset-within-word field), but since a pointer&#8217;s type includes the type of the thing pointed to, expressions including pointers can be type-checked at compile time. Pointer arithmetic is automatically scaled by the size of the pointed-to data type.<\/p>\n<p><br class=\"spacer_\" \/><\/p>\n<\/blockquote>\n<p><!--more--><\/p>\n<h4>1-dimensional array<\/h4>\n<p>In an 1-dimensional array things are quite simple. For example:<\/p>\n<pre lang=\"c\">int ar[5] = {1, 2, 3, 4, 5};<\/pre>\n<p>declares a 5 element integer array, where <code>ar<\/code> is a pointer to the beginning of the continuous memory location where the 5 integers are stored. So, <code>ar<\/code> is simply a a pointer to an int that points to the memory location of <code>ar[0]<\/code> item, thus <code>ar == &amp;ar[0]<\/code>.<\/p>\n<p>Now, what is important to understand is what happens when we have the following code: <code>(ar + 1)<\/code><\/p>\n<p>What happens is because we have declared <code>ar<\/code> as a pointer to an int, the compiler will actually do the following addition:<\/p>\n<p><code>(ar + 1*sizeof(int))<\/code> == (memory location that <code>ar<\/code> points) + (the size of 1 integer) == <code>&amp;ar[1]<\/code> == the memory location of the next integer after the one at <code>ar<\/code><\/p>\n<p>So, we can easily see that <code>*(ar + 1) == ar[1]<\/code>, since <code>(ar + 1) == &amp;ar[1]<\/code> (pointer <em>dereferencing<\/em>).<\/p>\n<p>So, if we want to simply print all the items of the array we can use the following two ways:<\/p>\n<p><br class=\"spacer_\" \/><\/p>\n<pre lang=\"c\">int i;\r\nfor (i = 0; i < ARRAY_SIZE; i++)\r\n printf(\"%d\\n\", ar[i]);\r\nfor (i = 0; i < ARRAY_SIZE; i++)\r\n printf(\"%d\\n\", *(ar + i));<\/pre>\n<p>That was simple!<\/p>\n<h4>2-dimensional array<\/h4>\n<p>Lets continue with a 2-dimensional array. For example:<\/p>\n<pre lang=\"c\">int ar[2][3] = {{1,2,3}, {4, 5, 6}};<\/pre>\n<p>Here things are more complicated. Lets take it one by one:<\/p>\n<p><code>ar<\/code> is again a pointer that points at the first element of the array. But this time the first element of the array is an array (3 int item array), so <code>ar<\/code> is not a pointer to an integer, but a pointer to an array of integers and to be precise a pointer to 3 consecutive ints. To make this clear, just see that <code>ar[j], j={0, 1}<\/code> are 3 int arrays.<\/p>\n<p>Now, since <code>ar<\/code> is a pointer to an array, we can understand that <code>ar<\/code> is a pointer to a pointer. Lets try to find some \"equalities\":<\/p>\n<ul>\n<li>as we said, <code>ar<\/code> points to the first array item (which happens to be also an array), so <code>ar == &amp;ar[0]<\/code>. <code>ar[0]<\/code> is a pointer to the first element of the (inner) array, so <code>ar[0] == &amp;ar[0][0]<\/code>. Since both the integer (<code>ar[0][0]<\/code>) and the array of 3 ints (<code>ar[0]<\/code>) begin on the same memory location, we have that <code>ar == ar[0].<\/code> <\/li>\n<li>the big difference lies when we want to add to the pointers in order to reference other array items. As we saw before, adding 1 to a pointer, increases the value by the size of the referenced item. So, <code>(ar + 1) != (ar[0] + 1)<\/code>, because in the first case the size of the 3-int array is added, while in the second case the size of int is added. <\/li>\n<li>Dereferencing a pointer or address (either by applying the * operator or the [ ] operator with an index) returns the value represented by the referred-to object. So, same as the 1-dimensional array example, <code>*ar[0] == a[0][0]<\/code>. Now, the <code>*ar<\/code> dereferencing gives the value contained in the <code>ar[0]<\/code>, which is also a pointer to the memory <code>&amp;ar[0][0]<\/code>. So, <code>*ar == &amp;ar[0][0]<\/code> and thus <code>**ar == *(&amp;ar[0][0]) == ar[0][0] == *ar[0]<\/code>. <\/li>\n<\/ul>\n<p>Having a pointer of a pointer, hence the address of an address, is called double indirection.<\/p>\n<p>Some fetching examples:<\/p>\n<ul>\n<li><code>ar[1] == *(ar + 1)<\/code><\/li>\n<li><code>ar[1][2] == *(ar[1] + 2) == *(*(ar + 1) + 2)<\/code><\/li>\n<\/ul>\n<p>Smooth..<\/p>\n<h4>N-dimensional arrays<\/h4>\n<p>What happens on N-dimensional arrays, when N > 2, is out of the scope of the article.. Just kidding, what happens follows exactly the same philosophy as in the 2-dimensional example. If N = 3, for example:<\/p>\n<ul>\n<li>***ar == **ar[0] == *ar[0][0] == *(&amp;ar[0][0][0])<\/li>\n<li>and, ar[1] == *(ar + 1)<\/li>\n<li>ar[1][2] == *(ar[1] + 2) == *(*(ar + 1) + 2)<\/li>\n<li>ar[1][2][3] == *(ar[1][2] + 3) == *(*(*(ar + 1) + 2) + 3)<\/li>\n<\/ul>\n<p>That's it, nice (?) and simple (?). Enjoy!<\/p>\n<p>Here is a program that prints all (un)equalities that I talked about:<\/p>\n<pre lang=\"c\">#include \r\n\r\n#define ARRAY_SIZE 5\r\n\r\nint main() {\r\n  \/\/1-dimensional array\r\n  int ar[ARRAY_SIZE] = {1, 2, 3, 4, 5};\r\n  printf(\"ar = %p, &ar[0] = %p\\n\", ar, &ar[0]);\r\n\r\n  printf(\"(ar + 1) = %p, &ar[1] = %p\\n\", (ar + 1), &ar[1]);\r\n  printf(\"*(ar + 1) = %d, ar[1] = %d\\n\", *(ar + 1), ar[1]);\r\n\r\n  int i;\r\n  for (i = 0; i < ARRAY_SIZE; i++) {\r\n    printf(\"%d,\", ar[i]);\r\n    printf(\"%d \", *(ar + i));\r\n  }\r\n  printf(\"\\n\");\r\n\r\n  \/\/2-dimensional array\r\n  int ar2[2][3] = {{1,2,3}, {4, 5, 6}};\r\n\r\n  printf(\"ar2 = %p, &#038;ar2[0] = %p\\n\", ar2, &#038;ar2[0]);\r\n  printf(\"ar2[0] = %p, &#038;ar2[0][0] = %p\\n\", ar2[0], &#038;ar2[0][0]);\r\n  printf(\"(ar2 + 1) = %p, (ar2[0] + 1) = %p\\n\", (ar2 + 1), (ar2[0] + 1));\r\n  printf(\"(ar2 + 1) - (ar2[0] + 1) = %X, 2*sizeof(int) = %d\\n\",\r\n    (int)(ar2 + 1) - (int)(ar2[0] + 1), 2*sizeof(int));\r\n  printf(\"*ar2[0] = %d, ar2[0][0] = %d\\n\", *ar2[0], ar2[0][0]);\r\n  printf(\"*ar2 = %p, &#038;ar2[0] = %p\\n\", *ar2, &#038;ar2[0]);\r\n  printf(\"**ar2 = %d, *(&#038;ar2[0][0]) = %d\\n\", **ar2, *(&#038;ar2[0][0]));\r\n\r\n  \/\/N-dimentional arrays, N = 3\r\n  int ar3[3][2][2] = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}};\r\n\r\n  printf(\"***ar3 = %d, **ar3[0] = %d, *ar3[0][0] = %d, *(&#038;ar3[0][0][0]) = %d\\n\",\r\n    ***ar3, **ar3[0], *ar3[0][0], *(&#038;ar3[0][0][0]));\r\n  printf(\"ar3[1] = %p, *(ar3 + 1) = %p\\n\", ar3[1], *(ar3 + 1));\r\n  printf(\"ar3[1][2] = %p, *(ar3[1] + 2) = %p, *(*(ar3 + 1) + 2) = %p\\n\",\r\n    ar3[1][2], *(ar3[1] + 2), *(*(ar3 + 1) + 2));\r\n  printf(\"ar3[1][2][2] = %d, *(ar3[1][2] + 2) = %d, *(*(*(ar3 + 1) + 2) + 2) = %d\\n\",\r\n    ar3[1][2][2], *(ar3[1][2] + 2), *(*(*(ar3 + 1) + 2) + 2));\r\n\r\n  return 0;\r\n}\r\n<\/pre>\n<p>That produced the following output in my machine:<\/p>\n<pre>ar = 0xbfdf65d8, &ar[0] = 0xbfdf65d8\r\n(ar + 1) = 0xbfdf65dc, &ar[1] = 0xbfdf65dc\r\n*(ar + 1) = 2, ar[1] = 2\r\n1,1 2,2 3,3 4,4 5,5\r\nar2 = 0xbfdf65c0, &ar2[0] = 0xbfdf65c0\r\nar2[0] = 0xbfdf65c0, &ar2[0][0] = 0xbfdf65c0\r\n(ar2 + 1) = 0xbfdf65cc, (ar2[0] + 1) = 0xbfdf65c4\r\n(ar2 + 1) - (ar2[0] + 1) = 8, 2*sizeof(int) = 8\r\n*ar2[0] = 1, ar2[0][0] = 1\r\n*ar2 = 0xbfdf65c0, &ar2[0] = 0xbfdf65c0\r\n**ar2 = 1, *(&ar2[0][0]) = 1\r\n***ar3 = 1, **ar3[0] = 1, *ar3[0][0] = 1, *(&ar3[0][0][0]) = 1\r\nar3[1] = 0xbfdf65a0, *(ar3 + 1) = 0xbfdf65a0\r\nar3[1][2] = 0xbfdf65b0, *(ar3[1] + 2) = 0xbfdf65b0,\r\n  *(*(ar3 + 1) + 2) = 0xbfdf65b0\r\nar3[1][2][2] = 11, *(ar3[1][2] + 2) = 11, *(*(*(ar3 + 1) + 2) + 2) = 11\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>As anyone who had programmed in C knows, pointers can be (also) used to access the data of an array. From the Wikipedia article about C language: C supports the use of pointers, a very simple type of reference that records, in effect, the address or location of an object or function in memory. Pointers [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[28],"tags":[29,30,27],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p1ouW6-28","_links":{"self":[{"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/posts\/132"}],"collection":[{"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/comments?post=132"}],"version-history":[{"count":23,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/posts\/132\/revisions"}],"predecessor-version":[{"id":651,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/posts\/132\/revisions\/651"}],"wp:attachment":[{"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/media?parent=132"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/categories?post=132"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/trigonakis.com\/blog\/wp-json\/wp\/v2\/tags?post=132"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}