The behavior of `swprintf` when passing` char const * `matches` L '% s` `specifier

I am writing an Excel plugin and should generate wchar_t output for Excel (although internally we are 100% char , and in fact the char limit is ASCII). At some point, I use swprintf to do the conversion:

 static wchar_t buffer[ 32369 ]; buffer[0] = swprintf( buffer + 1, sizeof(buffer) - 1, L"#%s!", message ); 

Excel displays some CJK characters, although message ( char const* type char const* ) is a character string with a null terminating character with no characters outside of printable ASCII (hexadecimal values ​​0x20-0x7E).

I tried this in a small test program, flushing the generated string in hexadecimal format, and it looks like VC ++ is processing the message as if it were wchar_t const* (although it seems to correctly recognize '\0' , although it is on one byte) ; this leads to wchar_t with values ​​like 0x6568 (and not 0x0068, 0x0065 , which I expected).

According to the C99 standard for the specifier "%s" swprintf must convert characters from char const* "as if by repeated calls to the mbrtowc function [...]". Is the behavior that I see is a bug in the Visual C ++ library, or is there something in the global region that I have to change?

(FWIW: when I compile and run my small test program with g ++, I get the behavior I expect. However, g ++ is not an option for our Excel plugins, at least not now.)

+4
source share
2 answers

Note that from swprintf from MSDN:

swprintf - widescreen version of sprintf; swprintf pointer arguments are wide character strings.

and then in the example:

 wchar_t buf[100]; int len = swprintf( buf, 100, L"%s", L"Hello world" ); 

at least Microsoft has documented this.

And then on the page format specifiers

s String When used with printf functions, a string with one byte character is specified; when used with wprintf functions, sets the widescreen string. Characters are printed before the first null character or until a precision value is reached.

And then

S String When used with printf functions, a widescreen string is specified; when used with functions, wprintf specifies a string with one byte character. Characters are printed before the first null character or until a precision value is reached.

So what you want is the upper case %S

See even the same question: Visual Studio swprintf makes all my% S formatters want wchar_t * instead of char * , where they suggest using %ls (always consider the wchar_t* parameter) and %hs (always consider the char* parameter)

+10
source

When invoking swprintf the % s specifier is interpreted as pointing to a wide string, that is, to the wchar_t pointer. Instead, use the % S format specifier (upper case S), as this will correctly use the passed char* message .

From the Microsoft documentation on printf type fonts:

  • s , String. When using functions, printf specifies a string with one byte character; when using functions, wprintf specifies a string with a wide character. Characters are printed before the first null character or until a precision value is reached.
  • S , String. When using functions, printf specifies a wide character string; when used with wprintf functions , sets a string with one byte character. Characters are printed before the first null character or until a precision value is reached.
+2
source

Source: https://habr.com/ru/post/1501438/


All Articles