Site Tools


wiki:wchar.h

Table of Contents

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.

wiki/wchar.h.md · Last modified: by 127.0.0.1