1. 9
  1.  

  2. 5

    While this is true (arrays are multiple objects of the same type packed together, while pointers only store memory addresses), it doesn’t make much difference between their usage, which is why the shortcut “array are pointers” is usually taken.

    The only difference between them that I can think of (regarding usage, not semantics) are :

    • no pointer arithmetic can be done on arrays
    • actual in-memory object size differ (as reported by sizeof())
    char a[5] = "12345";
    char *p = a;
    
    printf("a => %d bytes\n", sizeof(a)); // 5 bytes
    printf("p => %d bytes\n", sizeof(p)); // 8 bytes (on amd64)
    
    printf("++p: %s\n", ++p); // 2345
    printf("++a: %s\n", ++a); // compilation error: cannot increment value of type 'char[5]' (clang 14.0.0)
    
    

    But IMO when you use any of these techniques (in-memory object size or pointer arithmetic), you should already know the difference between both.

    I’ve happily used this shortcut to teach pointers to newcomers in C. Arrays are a much simpler concept to understand than pointers, so once they got it settled and start dealing with pointers I leverage their knowledge of arrays to explain pointers. I mention that there are subtle differences of course, but also that they shouldn’t care about it just yet. And I think that anyone who ever tried to teach pointers to a student will agree with me there: pointers are complex enough on their own to bother mentioning the differences I stated above.

    1. 6

      sizeof isn’t the only footgun. Consider:

      char foo[] = "12345";
      char *foo = "12345";
      

      Modern compilers will warn on the second of these. The first is allocating new storage in whatever scope you are writing in and copy that string. The second will store the string in read-only storage and give you a pointer. Generally, on a vaguely modern OS, the string on the second line will be in the read-only data section and will trap if you try to write to it. On older systems and some systems without an MMU, it will not trap, but if you do write to it then the next bit of code that tries to operation on the same string literal will be surprised to discover that it’s been modified.

    2. 3

      sadly when passing argument arrays become pointer

       void f(char my_array[5]) {
       }
      

      is actually:

       void f(char *my_array) {
       }
      

      at least for my memories of circa 2002