You can actually pass an array as an array in C99:<p><pre><code> #include <stdlib.h>
void f(size_t m, size_t n, float a[m][n])
{ for (size_t i = 0; i < m; i++) {
for (size_t j=0; j < n; j++) {
a[i][j] = 0;
}
}
}
int main(int argc, char* argv[]) {
float a[10][20];
f(10,20,a);
}
</code></pre>
This "conformant array" feature was supported in C99. GCC supports it. Microsoft didn't like it, though, and didn't implement it, so nobody uses it, and it was made optional in later versions of the C standard.<p>It doesn't do what it looks like it does. The last subscript is totally ignored by the compiler. For 1D arrays, it's not only ignored, the object is still passed as a pointer to the element type.<p>I once proposed making arrays in C size-safe by taking conformant arrays seriously and adding some features to make them more useful.[1] After much discussion, the idea was considered sound, but not popular enough. So buffer overflows in C continue.<p>I have great hopes for Rust.<p>[1] <a href="http://animats.com/papers/languages/safearraysforc43.pdf" rel="nofollow">http://animats.com/papers/languages/safearraysforc43.pdf</a>
When I was first learning C, pointers scared the crap out of me, and it took me longer to understand them than I am comfortable admitting to.<p>Then I got pointers and this big "NOW I get it"-moment and felt really clever.<p>And <i>then</i> came the moment I had a problem with pointers and arrays being interchangeable <i>most</i> of the time and became very confused about when they were not equivalent.<p>People who like C (which I do, too) will often point out C's perceived simplicity when compared with, say, C++, but C definitely does have its murky corners, and the need for backward compatibility with existing code will most likely prevent them from getting cleaned up.
One other difference on modern compilers relating specifically to character arrays:<p>This will work fine:<p><pre><code> char arr[] = "stuff";
printf("arr:%s\n", arr);
arr[0] = 'b'; arr[1] = 'l';
printf("arr:%s\n", arr);
</code></pre>
arr is allocated on the stack (not heap, sorry about the mistake) and is mutable.<p>But the following will segfault:<p><pre><code> char* ptr = "stuff";
printf("ptr:%s\n", ptr);
ptr[0] = 'b'; ptr[1] = '1';
printf("ptr:%s\n", ptr);
</code></pre>
Strings are allocated in the read-only data segment. Technically you can only write const char* ptr = "stuff", but due to wanting to remain backward compatibile, gcc will let you write the above and not even warn you unless you use -Wall or similar.
This is straight from Expert C Programming book, including the diagrams. It's dishonest to recycle and present it as if it's yours with a reference mention at the very bottom. This is not a reference, it's a copy.
Also sizeof is different.<p><pre><code> char a[20];
char *b;
</code></pre>
sizeof a -> the size of the array (20)<p>sizeof b -> the size of the pointer (8 on my machine)
Funny how old articles resurface suddenly :-) It's great that HN still likes technical content, though.<p>FWIW I also wrote a (shorter) follow-up post a few months later about multi-dimensional arrays and their relation to pointers-to-pointers: <a href="http://eli.thegreenplace.net/2010/04/06/pointers-vs-arrays-in-c-part-2d" rel="nofollow">http://eli.thegreenplace.net/2010/04/06/pointers-vs-arrays-i...</a>
I like to think of them as being different and the equivalence - in some cases - only comes from what is known as the "array-pointer-decay" semantic:<p><a href="http://www.lysator.liu.se/c/c-faq/c-2.html" rel="nofollow">http://www.lysator.liu.se/c/c-faq/c-2.html</a><p>This is why &a+n is not equivalent to a+n, something that a surprisingly large number of "C pointer tutorials" seem to get wrong.
Excellent. Years ago (15-20?) I wrote a program with the bug he mentions at the end. Way before Stack Overflow was a Google away. I could not work out why it crashed. I ended up rewriting it and it worked, but never understood what the bug was (in my mind it has been logged as 'don't extern arrays' ever since). I just read that and ah-ha!
Another interesting thing to know about pointer and arrays is:<p><pre><code> #include <stdio.h>
typedef int a_t[100];
int main(void)
{
int a[100];
a_t* p = &a;
// all printed pointer values are equal
printf("%p %p %p %p\n", (void*)a, (void*)&a, (void*)p, (void*)*p);
return 0;
}</code></pre>
Ah Betteridge's law of headlines at work!<p>Arrays are aggregates of contiguously allocated objects.<p>Pointers are values indicating the storage locations of objects.<p>Thus, not equivalent.<p>Pointers are involved when you access an array. That doesn't make it an array. Just like scanning written text on a piece of paper using your index finger does not mean that "paper" and "your index finger" are equivalent. That's true even if you always instantiate an index finger before evaluating a piece of paper: co-ocurrence is not equivalence.