Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Are pointers and arrays equivalent in C? (thegreenplace.net)
65 points by r11t on Oct 26, 2009 | hide | past | favorite | 23 comments


A slight tangent, but something that surprised me: The [] operator literally is just syntactic sugar for pointer dereferencing and addition, so that the following equivalence holds:

  a[b] == *(a + b);
The surprising consequence of this is that the following is legal:

  int foo[] = { 1, 2, 3 };
  int bar = 2[foo]; /* yes, this evaluates to 3 */
because

  *(2 + foo)
is legal, and + is commutative. This works for both pointers and arrays. I haven't worked out a practical use, though I suspect the C++ metaprogramming crowd might have. Obviously the equivalence only holds on the native types in C++ as [], + and * can each be separately overloaded.


No practical use?! Why, it's practically a requirement for IOCCC entries. :)


In fact, I recently only realised this myself this courtesy of this article (a tutorial on writing obfuscated C :)):

http://www.dreamincode.net/forums/index.php?showtopic=38102

It makes perfect sense when you consider the semantics of [], but I never would have thought to try it myself!


I apologize for initially considering you a crank, but gcc 4.2.1 agrees with you.


I'm like 99.9% sure it's in the standard. gcc -pedantic -ansi certainly doesn't complain.


The only problem is that in C++, overloading operator[] has to be a non-static member function. x[y] is treated as x.operator[](y) if x is of class type. So x[y] may not be the same as y[x] if they are class types. So maybe that has some useful property, but it isn't really the same.


C is not C++, though.


That is unbelievable! I never would have thought to try 2[foo] even though I knew that it was essentially just *(a+b).


First off, I think is is an interesting article highlighting the difference between pointer arithmetic and array access. As far as the title goes, I think the answer should be a quick and obvious no. Pointers are variables that contain a particular memory address. Arrays are CONSECUTIVE pieces of memory where the variable name holds the address of the first piece of allocated memory. Conceptually, this is very different and the article does quite a nice job explaining the low level details of why you cannot gloss over this difference. The bit about arrays being converted to pointers in functions is left on my to read pile for now...


The answer to the same question here: http://c-faq.com/aryptr/aryptrequiv.html

``pointer arithmetic and array indexing [that] are equivalent in C, pointers and arrays are different.''


No.

Array names are immutable. Pointer values may be mutable.

However, let's ignore that and consider "int a[10]; int * const p(a);"

sizeof(a) is the size of the array named a or 4 * sizeof(int). sizeof(p) is the size of the pointer named p.


sizeof(array) works in a block, but as a function parameter, it'll return sizeof(void*).

i.e. void f(int a[4]) { printf("%d", sizeof(a)); } int main() { int b[4]; f(b); } ... yields "4" (on my 32-bit machine)


Arrays and pointers are not the same type. Pointers are used to access array elements, however the variable itself is not a pointer type. It's an array of some other type (which can also be an array). In addition to automatic memory allocation that happens with an array, this matters whenever compile-time type-checking happens.

So I guess it depends on what you mean by "equivalent."


Also... Arrays have block scope. So if you have a function that declares an array, operates on it, then returns a pointer to that array, it's undefined behaviour.

This was very confusing to me when I learned C because it's one of those undefined behaviours that appears to work properly in trivial programs (at least with the compiler I was using).


If you have a function that declares anything and returns a pointer to it, it's undefined behavior. Because variables have block scope.


EDIT: ugh, this is not working right. I can't figure out how to get the asterisks to not italicize ( I was trying to show an example).

Variables have block scope, but storage duration need not. If you return a pointer to a block of memory allocated within a function, that is not undefined behaviour. If you return a pointer an array declared within the function that is (if you return a pointer to a static array declared within a function that is not). That's the contrast I was trying to point out.


Another difference is that:

    array[-1]
is not valid, while

    pointer[-1]
can be valid, such as if it points to the middle of a data set.


    struct {
      char somechar;
      char somearray[7];
    } foo = {'E', "xample"};

    printf("%c\n", foo.somearray[-1]); // prints 'E'
                                       // (depending on your compiler and the
                                       // struct-packing directions you gave it)


(depending on your compiler and the directions you gave it)

I don't think I was trust this piece of code in a commercial application. There is too much variation which would make it unreliable across platforms and compilers.


The negative array index here is a bit perverse, granted. But the general idea of using structs (with ideally controlled, but hopefully at least well-known, packing) is surprisingly common, in my experience. I've seen it used for defining binary file and wire formats (which is perhaps somewhat dodgy but there you have it) and, perhaps more appropriately, for EEPROM layouts and the like in embedded systems.


Some of you maybe interested in this course http://www.reddit.com/r/carlhprogramming


Thanks for the link, it's a great read.


  > Here’s a quote from Expert C Programming:
  >
  >   There is one difference between an array name and a
  >   pointer that must be kept in mind. A pointer is a    
  >   variable, so pa=a and pa++ are legal. But an array
  >   name is not a variable; constructions like a=pa and 
  >   a++ are illegal.
That's deep.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: