/* In this example, we are looking at arrays. Specifically, we are examinging the relationship between arrays and pointers. C. Andrews 2016-02-19 To compile: gcc -o 04-arrays 04-arrays.c -Wall To run: ./04-arrays */ #include int main(int argc, char * argv[]){ int a[5]; // create a simple array of integers of length 5 int *p = &a[0]; // create an integer pointer that points to the first element of a // load the array with some numbers for (int i = 0 ; i < 5; i ++){ a[i] = (i + 1)*2; } // print out the contents of the array for (int i = 0 ; i < 5; i ++){ printf("%d\n", a[i]); } // the first item in a and the contents of memory referenced by p are the same printf("%d %d\n", a[0], *p); // a is fundamentally just a pointer // we can assign p more directly because the "contents" of a is just the address of // the start of the array p = a; printf("%d %d\n", a[0], *p); // the value of a and p are the same printf("%#lx %#lx\n", (unsigned long)a, (unsigned long)p); // we can do math with pointers // addresses are at the byte level // when we add to a pointer, we add by the size of the type of value the // pointer points to p++; printf("%#lx: %d\n", (unsigned long)p, *p); // reset p to point to the start of a p = a; // we can use array notation with p the same way we can with a p[1] =64; printf("%d %d\n", a[1], p[1]); // since a is fundamentally a pointer, we can do pointer math with // array variables as well for (int i = 0; i < 5; i++){ printf("%d %d\n", *(p+1), *(a+i)); } // because a[i] is just fancy notation for *(a+i), and addition is communitive // i[a] is just as valid (just don't ever do this as anything other than a stupid // party trick printf("%d %d\n",a[2], 2[a]); // In C, arrays are just a block of values in memory with nothing else // there is no bounds checking, you can walk off the end and nothing will complain printf("%d %d\n",a[-2], a[25]); // in most circumstances, there isn't a way to recover the length of the array // to prevent this // The only exception is array variables that are explicitly sized as a was above // We can use sizeof to find out how much space was originally reserved for a // This, however, will give us the size in bytes, not the length of the array, // so we have to divide this by the size of individual elements. printf("%lu\n", sizeof(a)/sizeof(a[0])); // if we try this with p, which can otherwise be treated the same as a, // we get the amount of memory required to store the address, not the amount of space // to store the array, so this trick doesn't work // in general, you need to keep track of array lengths yourself and explicitly printf("%lu\n", sizeof(p)/sizeof(p[0])); // the other major difference is that we cannot do pointer math with a // if you uncomment the following lines the code will not compile //a++; //printf("%d\n", a[0]); // curiously, the "value" stored in a (the address of the start of the array) and // the location in memory of a are the same // in other words, a is something of a myth -- it has no real existance, unlike p // it is a fiction maintained by the compiler // this explains the small discrepancies between a and p // in truth, it is far more common for us to be working with pointers than // statically declared arrays like a printf("%#lx %#lx\n",(unsigned long)a, (unsigned long)(&a)); return 0; }