memchr(), memchr_isr()

Updated: May 06, 2022

Find the first occurrence of a character in a buffer

Synopsis:

#include <string.h>

void* memchr( void* buf,
              int ch,
              size_t length );

void* memchr_isr( void* buf,
                  int ch,
                  size_t length );

Arguments:

buf
The buffer that you want to search.
ch
The character that you're looking for.
length
The number of bytes to search in the buffer.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The memchr() function locates the first occurrence of ch (converted to an unsigned char) in the first length bytes of the buffer pointed to by buf. The memchr_isr() function is similar, but it's safe for you to use it in an interrupt service routine.

Note: These functions give sensible results only if &buf[length - 1] is within the memory range allocated for buf. For example, consider the following code:
char buf[16];
char *p = memchr(buf, 'a', 100);

If the letter a doesn't appear within buf and if the memory at buf + 40 happens to be an a, then the call returns &buf[40], but that's outside the allocated buffer and in most circumstances would represent a bogus return value. If a page boundary is crossed between buf and buf + 100, then the function can result in the delivery of a fatal signal to the process. The only way to avoid these issues is ensure that &buf[length - 1] is within the region allocated for buf.

Returns:

A pointer to the located character, or NULL if ch couldn't be found.

Examples:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
    char buffer[80];
    char* where;

    strcpy( buffer, "video x-rays" );

    where = (char *) memchr( buffer, 'x', 6 );
    if( where == NULL ) {
        printf( "'x' not found\n" );
    } else {
        printf( "%s\n", where );
    }

    where = (char *) memchr( buffer, 'r', 9 );
    if( where == NULL ) {
        printf( "'r' not found\n" );
    } else {
        printf( "%s\n", where );
    }
    
    return EXIT_SUCCESS;
}

produces the output:

'x' not found
rays

Environment variables:

LIBC_STRINGS
On certain targets, you can use this environment variable to select the implementation of memchr(). It doesn't affect the implementation of memchr_isr(). The value is one of the strings given below.
  • for AArch64 targets:
    • aarch64_neon — optimized for AARCH64 targets using NEON
    • generic — the default
  • for ARMv7 targets:
    • cortex_a9 — optimized for the ARM Cortex-A9 processor; assumes that no unaligned access is supported
    • cortex_a9_aligned — optimized for ARM Cortex-A9; requires that unaligned memory access be enabled on the platform. If memory access is misaligned, this implementation falls back to the NEON version.
    • cortex_a9_neon — optimized for ARM Cortex-A9 using NEON
    • generic — the default
    • krait — optimized for the Qualcomm Krait CPU
    • krait_neon — optimized for Qualcomm Krait using NEON

Processes that register ISRs shouldn't use the NEON versions.

Classification:

memchr() is ANSI, POSIX 1003.1; memchr_isr() is QNX Neutrino.

Table 1. memchr()
Safety:  
Cancellation point No
Interrupt handler Read the Caveats
Signal handler Yes
Thread Yes
Table 2. memchr_isr()
Safety:  
Cancellation point No
Interrupt handler Yes
Signal handler Yes
Thread Yes

Caveats:

Implementations of memchr() that are optimized using SIMD instructions aren't safe to use in an interrupt handler. These include the NEON implementations on ARMv7 and AArch64.