Hi Ben,

On 2026-02-21T09:47:12-0800, Ben Pfaff wrote:
> On Sat, Feb 21, 2026 at 1:38 AM Bruno Haible via Gnulib discussion
> list <[email protected]> wrote:
> > strchr is a red herring, because this way to define strnul is compiled
> > less efficiently than (s + strlen (s)). See attached example code.
> >
> > The better way is thus (s + strlen (s)), and since it evaluates s twice,
> > it means we need an inline function, not a macro. But we have the machinery
> > for inline functions in Gnulib.
> 
> Maybe it would be a good idea to suggest an update to the glibc manual,

Agree.

> because it says that strchr(s, '\0') is faster than s + strlen(s):

Huh; I'm curious about why that's said in the glibc manual.
I would be surprised if that were true, given strchr() must perform two
comparisons per iteration.  And indeed, some experiment shows that
s+strlen(s) is faster:

        alx@devuan:~/tmp$ diff -U9 strnul?.c
        --- strnul1.c   2026-02-21 21:08:11.932024735 +0100
        +++ strnul2.c   2026-02-21 21:08:15.718094220 +0100
        @@ -2,11 +2,11 @@
         #include <string.h>
         int
         main(int argc, char *argv[])
         {
                const char *p, *q;
                int n = atoi(argv[1]);
         
                p = argv[0];
                for (int i = 0; i < n; i++)
        -               q = p + strlen(p);
        +               q = strchr(p, '\0');
         }
        alx@devuan:~/tmp$ gcc -S -fno-builtin strnul?.c
        alx@devuan:~/tmp$ diff -U9 strnul?.s
        --- strnul1.s   2026-02-21 21:11:41.185153412 +0100
        +++ strnul2.s   2026-02-21 21:11:41.197153516 +0100
        @@ -1,10 +1,10 @@
        -       .file   "strnul1.c"
        +       .file   "strnul2.c"
                .text
                .globl  main
                .type   main, @function
         main:
         .LFB6:
                .cfi_startproc
                pushq   %rbp
                .cfi_def_cfa_offset 16
                .cfi_offset 6, -16
        @@ -20,22 +20,21 @@
                call    atoi@PLT
                movl    %eax, -8(%rbp)
                movq    -48(%rbp), %rax
                movq    (%rax), %rax
                movq    %rax, -16(%rbp)
                movl    $0, -4(%rbp)
                jmp     .L2
         .L3:
                movq    -16(%rbp), %rax
        +       movl    $0, %esi
                movq    %rax, %rdi
        -       call    strlen@PLT
        -       movq    -16(%rbp), %rdx
        -       addq    %rdx, %rax
        +       call    strchr@PLT
                movq    %rax, -24(%rbp)
                addl    $1, -4(%rbp)
         .L2:
                movl    -4(%rbp), %eax
                cmpl    -8(%rbp), %eax
                jl      .L3
                movl    $0, %eax
                leave
                .cfi_def_cfa 7, 8
        alx@devuan:~/tmp$ gcc -fno-builtin strnul1.c -o strnul1
        alx@devuan:~/tmp$ gcc -fno-builtin strnul2.c -o strnul2
        alx@devuan:~/tmp$ time ./strnul1 1000000000

        real    0m1.006s
        user    0m1.002s
        sys     0m0.004s
        alx@devuan:~/tmp$ time ./strnul2 1000000000

        real    0m1.243s
        user    0m1.239s
        sys     0m0.004s

The numbers are consistent over many runs.

Have a lovely night!
Alex

> 
> > One useful, but unusual, use of the strchr function is when one wants to 
> > have a
> > pointer pointing to the null byte terminating a string. This is often 
> > written in this way:
> >
> >  s += strlen (s);
> >
> > This is almost optimal but the addition operation duplicated a bit of the 
> > work
> > already done in the strlen function. A better solution is this:
> >
> >  s = strchr (s, '\0');
> >
> > There is no restriction on the second parameter of strchr so it could very 
> > well
> > also be zero. Those readers thinking very hard about this might now point 
> > out
> > that the strchr function is more expensive than the strlen function since we
> > have two abort criteria. This is right. But in the GNU C Library the
> > implementation of strchr is optimized in a special way so that strchr
> > actually is faster.
> 
> (See, e.g. 
> https://sourceware.org/glibc/manual/latest/html_node/Search-Functions.html)

-- 
<https://www.alejandro-colomar.es>

Attachment: signature.asc
Description: PGP signature

Reply via email to