简体   繁体   English

什么使指针比数组更快?

[英]What makes pointers faster than arrays?

I was googling and found the following syntax for pointers 我在Google上搜索并找到了以下指针语法

  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. 我不知道Pointers也可以以数组形式访问。 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. 我曾经使用*作为指针操作我使用[0]表示数组而* p表示指针操作,这就是为什么我不知道其他两件事。 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. 我读到使用指针的操作更快,这就是为什么C保持在顶部以便快速执行并且没有其他语言能够超越其坚固性的原因。

Now the real question: What makes the pointer operations faster? 现在真正的问题是:什么使指针操作更快?

1) *(p+0) the *(Value at address) that makes the trick or 1)*(p + 0)*(地址的值)制作技巧或

2) p[0] 2)p [0]

since 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. 当一个普通数组可以用作*(a + 1)(在地址上使用*值)时,就像指针一样。 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] . 我实际上不希望*(ptr + offset)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). (gcc 4.5.0,x86_64,没有优化)。 Or with -O3 或者使用-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. 如果阵列在本地堆栈作用域或静态存储器中分配,则阵列访问速度更快,因为它可以通过EBP寄存器中的值的偏移量或通过固定地址的直接偏移量直接访问,而不是尝试访问堆栈变量中指针的值,然后添加到该变量的值并解除引用。

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): 为了访问array[3]的值,编译器只会发出一个简单的命令(这是针对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. 因此,为了访问array[3]的值,只需要一条指令。 That's very fast. 那很快。

在您提供的示例中, p[1]不会比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. 静态创建的数组有自己的类型,它包含了编译时定义的大小,这使得它们在技术上与指针不同,但是对于所有密集的目的,示例中的数组名称和字符指针可以相同地使用。

Array is a pointer, there is no difference between p and a after 数组指针, pa之后没有区别

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 . ap都是指向char的指针,它们指向同一个地方 - 数组在内存中的开头

using "operator []" is equivalent to pointer arithmetic too 使用“operator []”也等同于指针算术

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. 这意味着指向数组开头的指针将被i * sizeof(char)移动到数组的第i个元素的位置。

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 对于循环的每次迭代,将产生类似b + i(又名为b by i * sizeof(char))和a + i(也称为i * sizeof(char)的移位)的算术,以及

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. 从这些计算中解脱出来,每次只能按char的大小移动两个指针。

Pointers being faster than arrays is coming from the following example. 比数组更快的指针来自以下示例。

Say you want to implement the strcpy function, ie copy one null-terminated string to another. 假设您要实现strcpy函数,即将一个以null结尾的字符串复制到另一个字符串。 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: 但有两件事:

  1. It's not pointers which are fast, it's algorithm using them for optimization. 它不是快速的指针,它是使用它们进行优化的算法。
  2. Optimizer can easily perform this kind of optimization automatically, so you probably end up with the same generated code anyway. 优化器可以轻松地自动执行这种优化,因此您最终可能会得到相同的生成代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM