wchar.h
If you need to work with non-ASCII text in C — printing accented characters to a terminal, comparing strings that contain Unicode letters, formatting locale-aware dates — you will eventually run into wchar_t. wchar.h (C95) provides wide character I/O and string functions for it: the wide-character mirror of <stdio.h> and <string.h>, with every function prefixed w or wcs.
#include <wchar.h> #include <locale.h> setlocale(LC_ALL, ""); // activate locale for correct output wchar_t *s = L"héllo wörld"; wprintf(L"length: %zu\n", wcslen(s)); // wcslen counts wchar_t units, not bytes // wide string functions mirror their narrow counterparts wcscpy(dst, src) wcscat(dst, src) wcscmp(a, b) wcschr(s, L'é') wcsstr(s, L"sub")
The encoding of wchar_t is implementation-defined: 32-bit UTF-32 on Linux, 16-bit UTF-16 on Windows. This means <wchar.h> code is not portable across platforms if it assumes a specific encoding. Wide I/O also comes with a mode restriction: a FILE stream switches between narrow and wide mode on first use, and you cannot mix printf and wprintf on the same stream.
wcsftime is the wide-character version of strftime. wcstol, wcstod, and similar functions convert wide strings to numbers.
mbsrtowcs and wcsrtombs convert between multibyte (typically UTF-8) and wide strings, using mbstate_t to track state across calls:
mbstate_t state = {0}; wchar_t wbuf[256]; const char *src = "héllo"; mbsrtowcs(wbuf, &src, 256, &state);
For new portable Unicode code, <uchar.h> (char16_t/char32_t) is preferable because the encoding is specified. <wchar.h> is most useful for locale-aware terminal output and for interfacing with system APIs on Linux that use wchar_t.
Practice
// compile: gcc -o wcdemo wcdemo.c // run: ./wcdemo // description: print a wide string and its character count vs byte count #include <wchar.h> #include <locale.h> #include <string.h> #include <stdio.h> int main(void) { setlocale(LC_ALL, ""); const wchar_t *ws = L"héllo"; const char *ns = "héllo"; // UTF-8: é is 2 bytes wprintf(L"wide string: %ls\n", ws); wprintf(L"wcslen: %zu (wchar_t units)\n", wcslen(ws)); printf( "strlen: %zu (bytes)\n", strlen(ns)); printf( "sizeof wchar_t: %zu\n", sizeof(wchar_t)); return 0; }
wcslen returns 5 (one unit per character). strlen returns 6 because é takes two bytes in UTF-8. sizeof(wchar_t) is 4 on Linux, so the wide string occupies 20 bytes in memory for five characters — useful to keep in mind when sizing buffers.
