Question

I am trying to get a sample code working and it uses the following lines:

   WCHAR cBuf[MAX_PATH];

    GetSharedMem(cBuf, MAX_PATH);

    printf("Child process read from shared memory: %S\n", cBuf);

get shared mem:

__declspec(dllexport) VOID __cdecl GetSharedMem(LPWSTR lpszBuf, DWORD cchSize) 
{ 
    LPWSTR lpszTmp; 

    // Get the address of the shared memory block

    lpszTmp = (LPWSTR) lpvMem; 

    // Copy from shared memory into the caller's buffer

    while (*lpszTmp && --cchSize) 
        *lpszBuf++ = *lpszTmp++; 
    *lpszBuf = '\0'; 
}

strangely I get an unknown specifier error on the printf line. %S is a MS extension and not ANSI compatible but I would've thought that it would be included by default. How do I turn this on?

I'm using microsoft visual studios, not sure how to check my options

Was it helpful?

Solution

From http://www.globalyzer.com/gzserver/help/localeSensitiveMethods/formatting.htm#larges

Unqualified String Specifiers (large %S)

These tables show how Windows and ANSI treat parameters based on the %S specifier and the style of function call (single, generic, or wide):

    Windows function                Specifier    Parameter needs to be
    printf/sprintf (single/MBCS)    %S           wchar_t*
    _tprintf/_stprintf (generic)    %S           (don't use)
    wprintf/swprintf (wide)         %S           char*

    ANSI function                   Specifier    Parameter needs to be
    printf/sprintf (single/MBCS)    %S           wchar_t*
    wprintf/swprintf (wide)         %S           wchar_t*

Both ANSI and Windows treat %S basically as opposite of %s in terms of single byte or wide, which ironically means that Windows and ANSI again handle these specifiers differently.

Note that ANSI in essence always treats %S in the same way as %ls, in other words it is always assumed to be wide string.

Windows on the other hand treats %S differently based on the type of function call. For single byte function calls, %S acts like the wide %ls specifier, but for wide functions calls, %S acts like the single byte %hs specifier.

This specifier should not be used for Windows Generic calls. Since %S is the "opposite" of %s, the parameter would need to be wide if the _UNICODE flag is off, and single byte if the _UNICODE flag is on. The TCHAR generic type does not work this way, and there's not "anti-TCHAR" kind of datatype.

I tried the following in Visual C++ 2010:

#include "stdafx.h"
#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    WCHAR cBuf[MAX_PATH];
    TCHAR tBuf[MAX_PATH];

    wcsncpy_s(cBuf, L"Testing\r\n", MAX_PATH);
    _tcsncpy_s(tBuf, _T("Testing\r\n"), MAX_PATH);

    printf("%S", cBuf); // Microsoft extension
    printf("%ls", cBuf); // works in VC++ 2010
    wprintf(L"%s", cBuf); // wide
    _tprintf(_T("%s"), tBuf); // single-byte/wide

    return 0;
}

Settings:

/ZI /nologo /W3 /WX- /Od /Oy- /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Yu"StdAfx.h" /Fp"Debug\TestWchar.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue

OTHER TIPS

To print a wide string:

wchar_t * str = /*...*/

printf("The string: %ls\n", str);
// or
wprintf(L"The string: %ls\n", str);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top