Closed madebr closed 5 months ago
MinGW suggests to use
%hs
instead of%s
, but Google tells me to use%ls
instead.
Depends on what the linked C library actually supports (msvcrt.dll, ucrt, msvcrXX.dll, whatever..)
Ah, I usually use %S, but I don't know if that's standard. This should definitely be fixed though, either way.
I think the choices are:
%ls
on *nix (sizeof(wchar_t) == 4
)%hs
on MinGW, for compatibility with Windows (gcc has -fshort-wchar
for this) (sizeof(wchar_t) == 2
)%S
on MSVC (sizeof(wchar_t) == 2
)* `%hs` on MinGW, for compatibility with Windows (gcc has `-fshort-wchar` for this) (`sizeof(wchar_t) == 2`) * `%S` on MSVC (`sizeof(wchar_t) == 2`)
This part I don't understand: Why is there a difference here between MinGW and MSVC? Does MinGW provide some kind of special treatment in printing of wchar_t strings? I think not: it is handled by the same library linked to residing on the Windows system: %whatever is interpreted by that C library. Otherwise what am I missing here?
I might have been wrong. Building the source below gives consistent behavior between platforms when using %S
.
#include <stddef.h>
#include <stdio.h>
int main() {
const wchar_t txt[] = L"Hello world!";
printf("%d S: %15S hs: %15hs ls: %15ls\n", sizeof(wchar_t), txt, txt, txt);
return 0;
}
$ gcc a.c && ./a.out && i686-w64-mingw32-gcc a.c && wine a.exe && x86_64-w64-mingw32-gcc a.c && wine a.exe
4 S: Hello world! hs: H ls: Hello world!
2 S: Hello world! hs: H ls: Hello world!
2 S: Hello world! hs: H ls: Hello world!
I don't know what %hs
is used for.
. Building the source below gives consistent behavior between platforms when using
%S
.
That's good, we should use %S
for it, then.
I wonder whether old msvcrt.dll (e.g. the one in winxp) supports it..
Should this one be closed now after https://github.com/libsdl-org/SDL/commit/1938d25b7ec90f6fe45aa59bd696fbc31643c584 ?
Yep!
When building the tests in c++ mode, mingw complains because
"%s"
is used as format string for wchar_t strings. here https://github.com/libsdl-org/SDL/blob/790cd395f54f458303fb3b4a4f8ed4fd62719e55/test/testautomation_stdlib.c#L377-L384MinGW suggests to use
%hs
instead of%s
, but Google tells me to use%ls
instead.All testautomation_stdlib.c wchar_t-related warnings
``` /home/maarten/projects/SDL/test/testautomation_stdlib.c: In function 'stdlib_swprintf': /home/maarten/projects/SDL/test/testautomation_stdlib.c:384:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 384 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:384:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 384 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:390:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 390 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:390:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 390 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:400:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 400 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:400:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 400 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:407:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 407 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:407:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 407 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:415:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 415 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:415:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 415 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:423:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 423 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:423:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 423 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:431:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 431 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:431:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 431 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:439:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 439 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:439:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 439 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:447:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 447 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:447:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 447 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:455:82: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 455 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:455:91: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 455 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: %s, got: %s", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:463:83: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 463 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:463:94: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 463 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:471:83: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 471 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:471:94: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 471 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:478:83: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 478 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:478:94: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 478 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:508:91: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 508 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:508:102: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 508 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:516:91: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 516 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:516:102: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 516 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:526:83: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'const wchar_t *' {aka 'const short unsigned int *'} [-Wformat=] 526 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~~~~~ | | | | char * const wchar_t * {aka const short unsigned int *} | %hs /home/maarten/projects/SDL/test/testautomation_stdlib.c:526:94: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'wchar_t *' {aka 'short unsigned int *'} [-Wformat=] 526 | SDLTest_AssertCheck(SDL_wcscmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); | ~^ ~~~~ | | | | char * wchar_t * {aka short unsigned int *} | %hs ```