2

I have the following code successfully compiled:

#include <io.h>
#include <fcntl.h>
#include <iostream>
#include <cstddef>
#include <cstdio>
int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    
    char16_t chinese[] = u"\u4e66\u4e2d\u81ea\u6709\u9ec4\u91d1\u5c4b";
    wprintf(L"String written with unicode codes: %ls \n", chinese);
    
    wchar_t arabic[] = L"أَبْجَدِيَّة عَرَبِيَّة";
    wprintf(L"String written with L-String: %ls \n", arabic);
    std::wcout << std::endl;  std::system("PAUSE");
}

It prints:

  • String written with unicode codes: 书中自有黄金屋
  • String written with L-String: أَبْجَدِيَّة عَرَبِيَّة

However, the compiler issues a warning for chinese case (not for arabic case):

warning C4477: 'wprintf' : format string '%ls' requires an argument of type 'wchar_t *', but variadic argument 1 has type 'char16_t *'

What would be then the correct wprintf format string?

Alex S.
  • 974
  • 1
  • 13
  • 18

2 Answers2

1

wchar_t is not the same as char16_t. wchar_t are 2 byte characters on windows, but (usually) 4 byte characters on linux. This is like the int vs. int16_t problem. The standard does not define wchar_t.

So the question is not what format specifier to use with wprintf. It's rather how to convert a char16_t string to a wchar_t string.

Under Windows you might get away with simply casting a char16_t to a wchar_t, which is what happens implicitly with wprintf, since it does not actually validate it's parameters. The warning C4477 is just a little help by the (Visual Studio?) compiler hinting at your problem.

But on other platforms you have to actually convert the string.

So the best solution would be something like this: wprintf("%ls", boost::utf16_to_wchar_t(chinese)); (I am just throwing in boost here, since they have conversion functions. I don't know the exact function to use).

Or alternatively use wchar_t escape sequences and define your chinese as a wchar_t* string.

Hajo Kirchhoff
  • 1,969
  • 8
  • 17
1

What would be then the correct wprintf format string?

There is no printf format specifier for char16_t. It does not exist.

You have to convert your char16_t string to multibyte string or wide string and print it then.

c16rtomb would be the standard C function to do it. Convert between string, u16string & u32string shows how to do it in C++.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111