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

