liveBook · Manning

Multibyte string

As explained in Modern C

A multibyte string is a null-terminated C string whose character sequences may represent extended characters with multiple bytes.

Output after selecting a locale

#include <locale.h> #include <stdio.h> int main(void) { setlocale(LC_ALL, ""); fputs("fär ínóff", stdout); fputc('\n', stdout); } The call to setlocale selects the native locale before the program writes extended characters. Without it, a terminal may display garbage; successful display also depends on the system being properly installed. section 14.3

A multibyte character is a sequence of bytes interpreted as one character of an extended character set. A multibyte string is an ordinary null-terminated C string containing such sequences. TAKEAWAY: A multibyte character contains no null byte, so the string can retain its usual null terminator and be passed to ordinary string-output functions such as fputs. Compatibility with ordinary strings does not mean that counting bytes counts characters. section 14.3

For formatted output, the distinction matters. A separator-drawing function prints its starting string with fputs, uses the custom helper mbsrlen to count its characters, prints enough horizontal-bar strings to fill the line, and then prints the ending string. Its count is not a count of bytes. section 14.3

  void draw_sep(char const start[static 1],
                char const end[static 1]) {
    fputs(start, stdout);
    size_t slen = mbsrlen(start, 0);
    size_t elen = 90 - mbsrlen(end, 0);
    for (size_t i = slen; i < elen; ++i) fputs(HBAR, stdout);
    fputs(end, stdout);
    fputc('\n', stdout);
  }
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":4}],[{\"line\":0,\"ch\":14},{\"line\":0,\"ch\":24}],[{\"line\":1,\"ch\":16},{\"line\":1,\"ch\":26}],[{\"line\":0,\"ch\":31},{\"line\":0,\"ch\":37}],[{\"line\":1,\"ch\":31},{\"line\":1,\"ch\":37}],[{\"line\":0,\"ch\":14},{\"line\":0,\"ch\":24}],[{\"line\":1,\"ch\":16},{\"line\":1,\"ch\":26}],[{\"line\":0,\"ch\":31},{\"line\":0,\"ch\":37}],[{\"line\":1,\"ch\":31},{\"line\":1,\"ch\":37}],[{\"line\":2,\"ch\":4},{\"line\":2,\"ch\":9}],[{\"line\":5,\"ch\":41},{\"line\":5,\"ch\":46}],[{\"line\":6,\"ch\":4},{\"line\":6,\"ch\":9}],[{\"line\":2,\"ch\":17},{\"line\":2,\"ch\":23}],[{\"line\":5,\"ch\":53},{\"line\":5,\"ch\":59}],[{\"line\":6,\"ch\":15},{\"line\":6,\"ch\":21}],[{\"line\":7,\"ch\":16},{\"line\":7,\"ch\":22}],[{\"line\":3,\"ch\":4},{\"line\":3,\"ch\":10}],[{\"line\":4,\"ch\":4},{\"line\":4,\"ch\":10}],[{\"line\":5,\"ch\":9},{\"line\":5,\"ch\":15}],[{\"line\":3,\"ch\":4},{\"line\":3,\"ch\":10}],[{\"line\":4,\"ch\":4},{\"line\":4,\"ch\":10}],[{\"line\":5,\"ch\":9},{\"line\":5,\"ch\":15}],[{\"line\":5,\"ch\":4},{\"line\":5,\"ch\":7}],[{\"line\":3,\"ch\":4},{\"line\":3,\"ch\":10}],[{\"line\":4,\"ch\":4},{\"line\":4,\"ch\":10}],[{\"line\":5,\"ch\":9},{\"line\":5,\"ch\":15}],[{\"line\":2,\"ch\":4},{\"line\":2,\"ch\":9}],[{\"line\":5,\"ch\":41},{\"line\":5,\"ch\":46}],[{\"line\":6,\"ch\":4},{\"line\":6,\"ch\":9}],[{\"line\":2,\"ch\":17},{\"line\":2,\"ch\":23}],[{\"line\":5,\"ch\":53},{\"line\":5,\"ch\":59}],[{\"line\":6,\"ch\":15},{\"line\":6,\"ch\":21}],[{\"line\":7,\"ch\":16},{\"line\":7,\"ch\":22}],[{\"line\":2,\"ch\":4},{\"line\":2,\"ch\":9}],[{\"line\":5,\"ch\":41},{\"line\":5,\"ch\":46}],[{\"line\":6,\"ch\":4},{\"line\":6,\"ch\":9}],[{\"line\":2,\"ch\":17},{\"line\":2,\"ch\":23}],[{\"line\":5,\"ch\":53},{\"line\":5,\"ch\":59}],[{\"line\":6,\"ch\":15},{\"line\":6,\"ch\":21}],[{\"line\":7,\"ch\":16},{\"line\":7,\"ch\":22}],[{\"line\":7,\"ch\":4},{\"line\":7,\"ch\":9}],[{\"line\":2,\"ch\":17},{\"line\":2,\"ch\":23}],[{\"line\":5,\"ch\":53},{\"line\":5,\"ch\":59}],[{\"line\":6,\"ch\":15},{\"line\":6,\"ch\":21}],[{\"line\":7,\"ch\":16},{\"line\":7,\"ch\":22}]]"}
!@%STYLE%@!

Inspect draw_sep for the division of labor: fputs writes each multibyte string, while mbsrlen supplies the counts used by the loop. section 14.3

The helper mbsrlen counts through mbsrtowcs without storing a converted string. It copies the supplied conversion state before the call and returns the resulting length; its implementation also handles an error return. This is an ad hoc helper, not a name to assume is provided by the C library. section 14.3

Related conversion interfaces serve different jobs:

  • mbsrtowcs converts a multibyte string to wide characters; mbsrdup uses a length check, allocation, and that conversion to make a wide-character copy. section 14.3
  • mbrtowc converts one multibyte character using conversion state; a character-search helper can use it while advancing through a multibyte string. section 14.3

TAKEAWAY: Use multibyte strings for extended-character text, but treat locale selection, character counting, conversion state, and error returns as deliberate parts of input and output—not as consequences of ordinary byte-oriented string handling. section 14.3 section 14.6

How Modern C covers it

How deep it goes
Defines the byte-sequence model and works through locale-dependent output, character counting, and conversion helpers.
Examples
Uses phonetic text, box-drawing separators, and helper implementations for counting and converting characters.
What it assumes
Assumes familiarity with ordinary C strings and output functions while defining multibyte characters and their string compatibility.
What you can do after
Build it from scratch: output extended-character strings and adapt conversion helpers for counting or copying them.
How it connects
Connects multibyte strings to locales, null-terminated strings, wide characters, conversion state, and C input/output.

Also explained in

Compare how 2 books explain multibyte string →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C. The section links point to the parts of the book it draws on.