Danijel
Danijel

Reputation: 8610

Accessing array elements via a pointer?

Again on [] vs *:

void func(const instance* I, const float* in, float* out)
{
    for(int i=0;i<N; i++)
    {
        // some calculation goes here
        out[i] = ... in[i] * I.something[i] ... ;
    }
}

Quite often I find that sub-function code is written in a way that arrays are not referenced with [], but extra pointers are introduced, for example:

void func(const instance* I, const float* in, float* out)
{
    const float* inp = in;
    float* outp = out;
    float* s = I->something;

    for(int i=0;i<N; i++)
    {
        // some calculation goes here
        outp++ = ... inp++ * s++ ... ;
    }
}

What is the primary reason for doing this: readability, performance or something else? Does it have any effect on performance?

Upvotes: 1

Views: 79

Answers (1)

0___________
0___________

Reputation: 67999

What is the primary reason for doing this: readability, performance or something else? Does it have any effect on performance?

  1. Usually we introduce new variables if we want to preserve the original parameters to be used later in the function.

example:

char *mystrcpy(char *dest, const char *src)
{
    char *workdest = dest;   // temp variable to be used instead of dest.
    while((*workdest++ = *src++));
    return dest;
}
  1. It usually does not have any effect on performance if you use an optimizing compiler (and enable the optimizations)

  2. Introducing new (theoretically not needed variables) may help split complicated logic into smaller easier to maintain parts. It also usually does not have any impact on the performance as compilers usually optimize it quite well.

  3. Indexes and pointer arithmetic have the same performance and in the most cases the code generated is the same.

example:

int *reverse(int *arr, size_t size)
{
    int *end, *saved = arr;
    if(arr && size > 1)
    {
        end = arr + size - 1;
        while(end > arr)
        {
            int tmp = *arr;
            *arr++ = *end;
            *end-- = tmp;
        }
    }
    return saved;
}

int *reverse1(int *arr, size_t num)
{
    if(arr && num > 1)
    {
        for(size_t i = 0; i < num/2; i++) 
        {
            int  temp;
            temp=arr[i];
            arr[i] = arr[num-(i+1)];
            arr[num-(i+1)]=temp;
        }
    }
    return arr;
}

and the resulting code:

reverse:
        mov     r8, rdi
        test    rdi, rdi
        je      .L2
        cmp     rsi, 1
        jbe     .L2
        lea     rax, [rdi-4+rsi*4]
        cmp     rdi, rax
        jnb     .L2
        mov     rdx, rdi
.L3:
        mov     ecx, DWORD PTR [rdx]
        mov     esi, DWORD PTR [rax]
        add     rdx, 4
        sub     rax, 4
        mov     DWORD PTR [rdx-4], esi
        mov     DWORD PTR [rax+4], ecx
        cmp     rdx, rax
        jb      .L3
.L2:
        mov     rax, r8
        ret
reverse1:
        mov     r8, rdi
        test    rdi, rdi
        je      .L18
        cmp     rsi, 1
        jbe     .L18
        lea     rdx, [rdi-4+rsi*4]
        shr     rsi
        mov     rax, rdi
        lea     rdi, [rdi+rsi*4]
.L15:
        mov     esi, DWORD PTR [rdx]
        mov     ecx, DWORD PTR [rax]
        add     rax, 4
        sub     rdx, 4
        mov     DWORD PTR [rax-4], esi
        mov     DWORD PTR [rdx+4], ecx
        cmp     rax, rdi
        jne     .L15
.L18:
        mov     rax, r8
        ret

https://godbolt.org/z/qTG59h

Upvotes: 2

Related Questions