Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are pointers arrays?

Here is the code I'm having trouble to understand:

char* myPtr = "example";
myPtr[1] = 'x';

How am I allowed to use myPtr[1]? Why can I choose positions like a do on arrays? myPtr is not even an array.

Obs. I know about lookup table, literal pooling and string literals, my concern is just how this even compile. I don't use pointers that much.

Can anyone help?

like image 812
Luiz Heringer Avatar asked Mar 09 '26 05:03

Luiz Heringer


2 Answers

Apparently you made an assumption that applicability of [] operator to something necessarily implies that that "something" is an array. This is not true. The built-in [] operator has no direct relation to arrays. The [] is just a shorthand for a combination of * and + operators: by definition a[b] means *(a + b), where one operand is required to be a pointer and another is required to be an integer.

Moreover, when you apply the [] operator to an actual array, that array gets implicitly converted to a pointer type first, and only then the resultant pointer can act as an operand of [] operator. This actually means the opposite of what you supposedly assumed initially: operator [] never works with arrays. By the time we get to the [] the array has already decayed to a pointer.

As a related side-note, this latter detail manifests itself in one obscure peculiarity of the first C language standard. In C89/90 the array-to-pointer conversion was not allowed for rvalue arrays, which also prevented the [] operator from working with such arrays

struct S { int a[10]; };

struct S foo(void) { struct S s = { 0 }; return s; }

int main() 
{
  foo().a[5]; 
  /* ERROR: cannot convert array to pointer, and therefore cannot use [] */

  return 0;
}

C99 expanded the applicability of that conversion thus making the above code valid.

like image 191
AnT Avatar answered Mar 11 '26 20:03

AnT


It compiles according to §5.2.1/1 [expr.sub] of the C++ standard:

A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type “array of T” or “pointer to T” and the other shall have unscoped enumeration or integral type. The result is of type “T”. The type “T” shall be a completely-defined object type.

The expression E1[E2] is identical (by definition) to *((E1)+(E2)), except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.

Since "example" has type char const[8] it may decay to char const* (it used to decay to char* as well, but it's mostly a relict of the past) which makes it a pointer.

At which point the expression myPtr[1] becomes *(myPtr + 1) which is well defined.

like image 43
Shoe Avatar answered Mar 11 '26 20:03

Shoe