What makes pointers faster than arrays?
I was googling and found the following syntax for pointers
void main()
{
char a[10]="helloworld";
char *p=a;
printf("%c",p[0]);
}
I didnt know that Pointers can be accessed in the array form too. I used to use * for pointer operations I used a[0] for arrays and *p for pointer operations, which is why I didnt know the other 2 things. Now from the above, we can access the second element of array in any one of the following ways
printf("%C",a[1]); \\ this is the array
printf("%c",*(a+1)); \\ this is the array using *
printf("%c", p[1]); \\ using the pointer
printf("%C",*(p+1)); \\ using the pointer
Now I wonder: which is the faster operation? I read that operations using pointers are faster, and that this is why C stays at the top for fast execution and that no other language can beat its fastness.
Now the real question: What makes the pointer operations faster?
1) *(p+0) the *(Value at address) that makes the trick or
2) p[0]
sin开发者_JAVA百科ce we use
*(a+1) or *(p+1) both are same
a[1] or p[1] both are same
when a normal array can be used as *(a+1)( which uses * value at address) like a pointer. why do we use pointers for faster operations? When both have the same syntax, when normal array and pointer uses * in those syntaxes why pointers are faster?
But guys please tell me then why we use pointers ? My professor told me pointers are faster because they point to address rather a variable should be searched in the location.
I wouldn't actually expect *(ptr + offset)
to be faster than ptr[offset]
. In fact, on my machine, the following functions are compiled into exactly the same assembly code:
int
ArrayRef(int* array, int index)
{
return array[index];
}
int
PointerRef(int* array, int index)
{
return *(array + index);
}
which (cleaned up) looks like:
ArrayRef:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
movl %esi, -12(%rbp)
movl -12(%rbp), %eax
cltq
salq $2, %rax
addq -8(%rbp), %rax
movl (%rax), %eax
leave
ret
PointerRef:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
movl %esi, -12(%rbp)
movl -12(%rbp), %eax
cltq
salq $2, %rax
addq -8(%rbp), %rax
movl (%rax), %eax
leave
ret
(gcc 4.5.0, x86_64, no optimisations). Or with -O3
ArrayRef:
movslq %esi, %rsi
movl (%rdi,%rsi,4), %eax
ret
PointerRef:
movslq %esi, %rsi
movl (%rdi,%rsi,4), %eax
ret
Array access is faster if the array is allocated in the local stack scope or in static memory since it can be directly accessed via an offset of the value in the EBP
register or via a direct offset from a fixed address, rather than attempting to access the value of a pointer in a stack variable, and then adding to that variable's value and dereferencing.
For instance, if you write you array like:
int main()
{
int array[5] = {1, 2, 3, 4, 5};
//... more code
return 0;
}
In order to access the value at array[3]
, the complier will only issue a simple command like (this is for x86):
MOV -8(%ebp), %eax
This is because if we look at the stack, we would see the following:
EBP + 4 : Return Address
EBP : Previous function's stack activation record
EBP - 4 : array[4]
EBP - 8 : array[3]
EBP - 12: array[2]
EBP - 16: array[1]
EBP - 20: array[0]
So in order to access the value at array[3]
, only one instruction is needed. That's very fast.
In the examples that you provided, p[1]
will not be faster than a[1]
.
An array name is essentially the pointer to the first element of that array - so, they should be pretty much the same.
Statically created arrays have their own type which incorporates their compile-time defined size which makes them different than pointers technically, but for all intensive purposes the array name and the character pointer in your example can be used identically.
Pointers being faster than arrays is coming from the following example.
Say you want to implement the strcpy
function, i.e. copy one null-terminated string to another. Let's look at two examples:
First one:
char* strcpy(char* dest, const char* src)
{
int i = 0;
while( src[i] != '\0' ) {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return dest;
}
Second one:
char* strcpy(char* dest, const char* src)
{
char *save = dest;
while( *src != '\0' )
{
*dest++ = *src++;
}
*dest = '\0';
return save;
}
The second example is implemented more efficiently, cause it does less memory modifications in each iteration, and it uses pointers instead of arrays. But there are two things:
- It's not pointers which are fast, it's algorithm using them for optimization.
- Optimizer can easily perform this kind of optimization automatically, so you probably end up with the same generated code anyway.
Array is a pointer, there is no difference between p and a after
char a[10]="helloworld";
char *p=a;
both a and p are a pointer to char and they are pointing to the same place - beginning of your array in memory.
using "operator []" is equivalent to pointer arithmetic too
a[i]
will be substituted to
*(a+i)
it means that pointer to the beginning of the array will be shifted by i*sizeof(char) to the place of i-th element of your array.
The real difference in time appears when you try loop over all elements, for example, copy the string:
char a[10] = "helloworld";
char b[10];
for (int i = 0; i < 10; ++i) b[i] = a[i]; // using array element accessing method
will produce arithmetic like b+i (aka b shift by i*sizeof(char) ) and a+i (aka a shift by i*sizeof(char) ) for each iteration of loop, and
char a[10] = "helloworld";
char b[10];
char *_a, *_b;
for (_a = a, _b = b; *_a != '\0'; ++_a, ++_b) *_a = *_b; // using pointers arithmetic method
*b = '\0';
is free from this those calculations, you only shift two pointers by size of char each time.
精彩评论