Truncating Incomplete UTF-8 character
There is currently no error checking to validate that this is valid UTF-8. If this is deliberate it should be documented.

You are testing the 1's at the top of a UTF-8 encoded string. But not correctly validating the trailing 0.

  if ((*cptr &amp; 0xC0) == 0x80) { ...
  if ((*cptr &amp; 0xF8) == 0xF0) { ...
  if ((*cptr &amp; 0xF0) == 0xE0) { ...
  if ((*cptr &amp; 0xE0) == 0xC0) { ...
         ///   ^^^^  You should extend the mask one more bit
         ///         So that your test validates that the next
         ///         bit is zero. 


The way your function is written it will mutate the string if it finds a partial. This may not always be necessary I would break this into two functions. One that finds the amount of mutation needed and another that does the mutation. That way another user can potentially use only the non mutating part and get better performance (say if they were passing it to a function using iterators).

 std::size_t trimEndUTF8(std::string&amp; str) {
     std::size_t trim = findEndUTF8Trim(str);
     str.resize(str.size() - trim);
     return trim;
 }


If you implement the above function split. You now make it easy for your self to implement a slight return optimization.

 if ((*cptr &amp; 0xF8) == 0xF0) {
     if (num == 4) {
         return 0;
     }

     // break;
     // Change your break into a return.
     //
     // Because we are not mutating we don't need to worry about
     // changing the input in thus function and can just return the
     // size of the trim. Since this is the head character of a UTF-8
     // sequence the next character must be end of a UTF-8 character.
     //
     return num; // or is it num + 1 you should check.
 }


Prefer not to use yoda conditionals.

 for (int i = 0; 6 &gt; i; ++i)
                 ^^^^^  Yoda conditional


They are a cognitive drain and less intuitive to read (unless you are yoda). Prefer the more traditional style as it makes it easy to read fof developers.

 for (int i = 0; i &lt; 6; ++i)


Note you are assuming there are at least 6 characters in the string. I would not do that (especially since people are likely to throw all kinds of crap at it). A badly formed UTF-8 string is going to cause undefined behavior.

Standard warning about:

using namespace std;


Read any other C++ review on this site. We say don't use this. Read another review and you will find why.

Naming conventions. It is more traditional to use an initial lowercase letter for objects(this includes functions/methods).

ssize_t findEndUTF8Trim(std::string const&amp; str) {

    // If the last character is a single character return
    // Don't need to do any further checking or trimming.
    if ((str.back() &amp; 0x80) == 0x00)
        return 0;
    }

    // Check that we have a valid UTF-8 sequence.
    char const* cptr = &amp;str.back();
    int const   end  = std::min(6, str.size()); // Max theoritical len == 6
    for (int num = 1; num &lt;= end; ++num, --cptr) {
        if ((*cptr &amp; 0xF8) == 0xF0) { return (num == 4) ? 0 : num; } 
        if ((*cptr &amp; 0xF0) == 0xE0) { return (num == 3) ? 0 : num; }
        if ((*cptr &amp; 0xE0) == 0xC0) { return (num == 2) ? 0 : num; }  
    }
    // If reach here then there is a malformed UTF-8 character sequence.
    throw std::runtime_error("Unexpected UTF-8 string");
}