Accessing memory through pointers is considered more efficient than accessing memory through an array.
This could be true in the past when compilers were relatively stupid animals. You just need to take a look at some of the gcc code output in high optimization modes to find out that this is no longer the case. Some of this code is very hard to understand, but once you do, its brightness is obvious.
A decent compiler will generate the same code for accessing pointers and accessing an array, and you probably shouldn't worry about this level of performance. The people who write compilers know much more about their target architectures than mere mortals. Focus on the macro level when optimizing your code (choosing an algorithm, etc.) and trust your tools to do their job.
In fact, I am surprised that the compiler did not optimize the whole
temp = a[0];
since temp overwritten on the very next line with a different value and a is in no way marked volatile .
I remember the urban myth a long time ago about the benchmark for the last VAX Fortran compiler (showing my age here), which was several orders of magnitude superior to its competitors.
It turns out that the compiler found out that the result of calculating the standard was not used anywhere, so he optimized the entire calculation cycle in oblivion. Consequently, a significant improvement in speed.
Update. The reason that optimized code is more efficient in your particular case is because of how you find the location. a will be in a fixed location selected at the time of the connection / download, and the link to it will be fixed at the same time. Thus, a[0] or indeed a[any constant] will be in a fixed place.
And p itself will also be in a fixed location for the same reason. But *p (contents of p ) is a variable and therefore will have an additional search to find the correct memory location.
You will probably find that having another variable x set to 0 (not const ), and using a[x] will also lead to additional calculations.
In one of your comments you indicate:
The execution, as you suggested, led to 3 instructions for accessing memory through arrays (selecting an index, selecting an array element, saving to temp). But I still do not see the effectiveness .: - (
My answer to this is that you most likely will not see the effectiveness of using pointers. Modern compilers are more than the task of finding out that array operations and pointer operations can be turned into the same basic machine code.
In fact, without optimization, pointer code may be less efficient. Consider the following translations:
int *pa, i, a[10]; for (i = 0; i < 10; i++) a[i] = 100; /* movl $0, -16(%ebp) ; this is i, init to 0 L2: cmpl $9, -16(%ebp) ; from 0 to 9 jg L3 movl -16(%ebp), %eax ; load i into register movl $100, -72(%ebp,%eax,4) ; store 100 based on array/i leal -16(%ebp), %eax ; get address of i incl (%eax) ; increment jmp L2 ; and loop L3: */ for (pa = a; pa < a + 10; pa++) *pa = 100; /* leal -72(%ebp), %eax movl %eax, -12(%ebp) ; this is pa, init to &a[0] L5: leal -72(%ebp), %eax addl $40, %eax cmpl -12(%ebp), %eax ; is pa at &(a[10]) jbe L6 ; yes, stop movl -12(%ebp), %eax ; get pa movl $100, (%eax) ; store 100 leal -12(%ebp), %eax ; get pa addl $4, (%eax) ; add 4 (sizeof int) jmp L5 ; loop around L6: */
In this example, you can see that the pointer example is longer and redundant. It loads pa into %eax several times, without changing it or changing %eax between pa and &(a[10]) . The default optimization is mostly missing here.
When you switch to optimization level 2, you get the code:
xorl %eax, %eax L5: movl $100, %edx movl %edx, -56(%ebp,%eax,4) incl %eax cmpl $9, %eax jle L5
for the array version and:
leal -56(%ebp), %eax leal -16(%ebp), %edx jmp L14 L16: movl $100, (%eax) addl $4, %eax L14: cmpl %eax, %edx ja L16
for the pointer version.
I am not going to analyze the clock cycles here (since it works too much, and I'm mostly lazy), but I will point out one thing. There is not much difference in the code for both versions in terms of assembler instructions, and given the speeds that modern processors work with, you will not notice the difference if you do not perform billions of these operations. I always prefer to write code for readability and only worry about performance if this becomes a problem.
As an aside, this statement you refer to:
5.3 Pointers and arrays: the version of the pointer will generally be faster, but at least to the uninitiated, it’s a little harder to understand right away.
refers to the earliest versions of K & R, including my ancient 1978th, where functions were still written:
getint(pn) int *pn; { ... }
Compilers have come a very long way since.