3

With current C compilers, is it still true that using the array syntax (a[i]) is slower than using pointers (*(p+i))?

cfischer
  • 24,452
  • 37
  • 131
  • 214

10 Answers10

11

They are exactly equivalent. Array access is syntactic sugar for pointer math.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 1
    This isn't necessarily true. Assuming `a` is an array and `p` is a pointer, then `a[i]` involves adding a constant and a variable, whereas `p[i]` involves adding two variables. – Oliver Charlesworth Nov 14 '10 at 15:02
8

No, according to the C and C++ standards a[i] is by definition equivalent to *(a+i). this also implies that a[1] is equivalent to 1[a]. Try it :)

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
8

They should be the same. But:

for( i = 0; i < ...; ++ i ) ... array[i] ...

could be slower than:

for( p = array; *p; ++ p ) ... *p ...

because in the former case compiler could need to do *(array+i), while in the second you just do (*p).

In trivial cases, however, compiler should be able to optimize and generate the same machine code.

peoro
  • 25,562
  • 20
  • 98
  • 150
  • instead of "might be able" I would say "should be able" :) – Armen Tsirunyan Nov 14 '10 at 13:55
  • 2
    Indeed, "might be able" was correct. For example, older versions of some compilers (namely, MSVC) compiled the first example into a more efficient code. – Vlad Nov 14 '10 at 14:02
  • @Vlad A compiler may not do it, you are right, but it should, because if it doesn't, it is a bad compiler :) IMHO – Armen Tsirunyan Nov 14 '10 at 14:23
  • There are a lot of embedded compilers that can't do this optimization. When working with a new compiler/platform, be sure to try both and look at the assembly listing file to be sure they generate equivalent code. – tomlogic Nov 14 '10 at 16:58
  • By the way, in the second code compiler might be unable to prove that `p` cannot be altered during the execution of the loop body; this could potentially prevent some optimizations. If `i` is defined locally (close to the actual loop), a sophisticated compiler may potentially make use of it. – Vlad Nov 14 '10 at 18:42
5

Hell No! a[i] is always equivalent to *(a+i).

a[i] = *(a + i) = *(i + a) =i[a];

Community
  • 1
  • 1
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
3

On x86 or x86_64, using p[i] or *(p+i) (note: these two forms are identical in the C language) may be faster than incrementing p at each step of the loop, assuming you need to keep i around for some other purpose already. The x86 architecture has efficient addressing for base/offset usage like this, including scaling the offset by small powers of 2.

On the other hand, if you can eliminate i by incrementing p, you may reduce the number of registers needed in you loop, which could allow further optimization. Here are some quick thoughts on the relative cost in various cases on x86:

  • If you array a has static storage duration (static or extern global) in non-PIC-compiled code, the a[i] and *p (with no i) methods use the same number of registers (e.g. 0xdeadbeef(,%ecx,4) vs (%esi)).
  • If Your array a is automatic (local stack variable) and not a variable-length array, the a[i] and *p methods use the same number of registers (e.g. 12(%esp,%ecx,4) vs (%esi) where %esp, the stack pointer, is already reserved anyway).
  • If your array a has static storage duration and your code is compiled as PIC, a[i] is probably significantly more expensive than the *p method, even if you have to keep i around for another purpose anyway.
  • If your array a is not an array variable in the current scope, but a pointer to an array passed to your function from somewhere else, then a[i] takes one more register than *p (e.g. (%eax,%ecx,4) vs (%esi)).
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
2

There may be some circumstances where something like

while (*s++ = *d++)
   ;

might be faster than

while (s[i] = d[i])
   i++;

but even that will probably be optimized away by good compilers.

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
  • 1
    If none of the 3 variables are used after the loop, a good compiler will generate the same code for both sources. However, a lot of code *does* depend on the values - either it wants to keep using the original `s` and `d` pointers (in which case, "optimizing" the second loop to the first would require backign up and restoring their values), or wants to use the final value of `i` (in which case the optimization would need to save the original value of `s` or `d` and subtract at the end). Not that it can't be done, but issues like these complicate the situation a good bit. – R.. GitHub STOP HELPING ICE Nov 14 '10 at 23:37
1

The compiler will translate them to pointer code anyway, it just makes it easier to use them.

Think of array operator as an inline function for the pointer equivalent.

Aurel Bílý
  • 7,068
  • 1
  • 21
  • 34
1

They are equivalent. But algorithms that use the array syntax are typically written

int a[];
for (int n = 0; n < size; n++) { ... Do stuff with a[n]; }

which needs one more addition for each access to an element of a than

int a[size];
int *end = a + size;
for (int *i = a; i != end; ++i) { ... Do the same stuff with *i ; }

Some compilers might optimize the first version into the second though.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
1

It's obvious that's not what he means, this should help.

// which is faster? *t or t[i]?
process_some_array(T *t, size_t n)
{
    T *end = &t[n];
    for (T *t = t; t < end; ++t)
        // do stuff with *t
    for (size_t i = 0; i < n; ++i)
        // do stuff with t[i]
}

The answer is not as long as your compiler has no optimization whatsoever. For the general case you should not worry about the difference, as it is miniscule if present at all. Furthermore it's generally easier for yourself, and your fellows to parse and debug.

If this is not what you meant, I'm afraid it's a stupid question, see one of the other answers.

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
  • ++ for good thinking, but BTW, if you use an adjective that implies an insult, even if only conditionally applied, it feels to the author like a punch in the gut. It took me a long time to learn that too. – Mike Dunlavey Nov 15 '10 at 19:37
0

Pointer and Array both are accessing through address.Array is behave like a constant pointer and pointer used to hold the address of any value.So same thing is both access the value through address. On account of that both are exactly equivalent.

Varun Chhangani
  • 1,116
  • 3
  • 13
  • 18