String trim functions with destination size limitation 3 string trimming functions:
  Trim whitespace from the beginning of a string.
  Trim whitespace from the end of a string.
  Trim whitespace from both ends of a string. 


Looking to improve code for:


Correctness (tested code - but so far no holes) - especially overlapping src/dest cases.
Design
Portability (3 tried: MS, *nix, embedded)
Efficiency


Note: (unsigned char) used as unless x==EOF, isspace(x) is not defined when x &lt; 0.

/* String trim functions
 * 
 * Result is sized limited.
 * Overlapping source and destination is OK.
 * Pointer parameters are assumed to point to valid strings spaces.
 */

#include &lt;ctype.h&gt;
#include &lt;stddef.h&gt;
#include &lt;string.h&gt;

// Return string beginning with first non-white-space in string `src`
// Return NULL when destination is too small, `dest` unchanged.

char *trim_begin(char *dest, size_t dest_size, const char *src) {
  while (isspace((unsigned char) *src)) {
    src++;
  }
  size_t src_size = strlen(src) + 1;
  if (src_size &gt; dest_size) {
    return NULL;
  }
  return memmove(dest, src, src_size);
}

// Return string beginning string `src` but not including any of its trailing 
//   white-spaces.
// Return NULL when destination is too small, `dest` unchanged.

char *trim_end(char *dest, size_t dest_size, const char *src) {
  size_t len = strlen(src);
  while (len &gt; 0 &amp;&amp; isspace((unsigned char) src[len - 1])) {
    len--;
  }
  size_t src_size = len + 1;
  if (src_size &gt; dest_size) {
    return NULL;
  }
  memmove(dest, src, len);
  dest[len] = 0;
  return dest;
}

// Return string beginning with first non-white-space in string `src` but not 
//   including any of its trailing white-spaces.
// Return NULL when destination is too small, `dest` unchanged.

char *trim(char *dest, size_t dest_size, const char *src) {
  while (isspace((unsigned char) *src)) {
    src++;
  }
  return trim_end(dest, dest_size, src);
}
Repeated code

size_t src_size = strlen(src) + 1;
if (src_size &gt; dest_size) {
  return NULL;
}
return memmove(dest, src, src_size);


is a good candidate for a function (safe_memmove or something similar).



- Optimistic loops while (isspace((unsigned char) *src)) may never stop: '\0' is not a white space. Test for end of string explicitly:

    while (*src &amp;&amp; isspace((unsigned char) *src))



  Red face above. I don't know what I was thinking.


Portability. A free-standing environment doesn't have to provide memmove or strlen or isspace. Only features confined in &lt;float.h&gt;, &lt;iso646.h&gt;, &lt;limits.h&gt;, &lt;stdarg.h&gt;, &lt;stdbool.h&gt;, &lt;stddef.h&gt;, and &lt;stdint.h&gt; are mandatory. I am afraid that to claim embedded portability you need to implement optional features yourself.

Sorry for nitpicking.