Anique
Anique

Reputation: 71

Can someone explain the difference between these 2 for loops?

int n = strlen(s)
for (int i = 0; i < n; i++)
{
printf("%c", s[i]);

}

for (int i = 0; i <strlen(s); i++)
{
printf("%c", s[i]);
}

What I'm trying to ask is what is happening in memory(under the hood). Let's say the string length is 4, is 4 assigned to n, and would that make it easier for the compiler to compile? In the second code, would the compiler have to check what the string length of s is over and over? Is the point of the first code to make the compiler remember the string length is so it doesn't need to check for it every time. I'm sorry if my question isn't clear enough, telling me how to improve would be greatly appreciated.

Upvotes: 1

Views: 75

Answers (2)

0___________
0___________

Reputation: 67476

The main difference is that the first loop will call strlen on every iteration.

int foo(const char *s)
{
    for (int i = 0; i <strlen(s); i++)
    {
        printf("%c", s[i]); 
    }
    return 0;
}

int bar(const char *s)
{
    int n = strlen(s);
    for (int i = 0; i < n; i++)
    {
        printf("%c", s[i]);
    }
    return n;
}

and the resulting code:

foo:
        push    rbp
        mov     rbp, rdi
        push    rbx
        xor     ebx, ebx
        sub     rsp, 8
        jmp     .L2
.L3:
        movsx   edi, BYTE PTR [rbp+0+rbx]
        add     rbx, 1
        call    putchar
.L2:
        mov     rdi, rbp
        call    strlen
        cmp     rax, rbx
        ja      .L3
        add     rsp, 8
        xor     eax, eax
        pop     rbx
        pop     rbp
        ret
bar:
        push    r12
        push    rbp
        push    rbx
        mov     rbx, rdi
        call    strlen
        mov     r12, rax
        test    eax, eax
        jle     .L6
        lea     eax, [rax-1]
        lea     rbp, [rbx+1+rax]
.L8:
        movsx   edi, BYTE PTR [rbx]
        add     rbx, 1
        call    putchar
        cmp     rbx, rbp
        jne     .L8
.L6:
        mov     eax, r12d
        pop     rbx
        pop     rbp
        pop     r12
        ret

(gcc -O3) https://godbolt.org/z/1oh991

Upvotes: 1

Acorn
Acorn

Reputation: 26066

In the second code, would the compiler have to check what the string length of s is over and over

That's exactly right. The condition of a for loop is evaluated every iteration. Therefore, you should cache the length (or any other result that does not change in each iteration, for that matter).

In this case, as people pointed out, you can do even better avoiding to compute the length since you are iterating the string anyway.

Upvotes: 1

Related Questions