1

I was learning how to use wchar, but I am unable to copy the char using snprintf(). I want to copy the text from a to b but it never prints the value. What am I doing wrong? And I want to use snprintf and nothing else.

#include <wchar.h>
#include <stdio.h>

void main() {

    printf("Start\n");
    wchar_t a[12];
    wchar_t b[] = L"984567";

    snprintf(a, sizeof(a), "%ls\0", b);

    printf("%ls\n", a);
    printf("%ls\n", b);

    printf("end\n");
}

//Output

Start

984567

end

Community
  • 1
  • 1
chettyharish
  • 1,704
  • 7
  • 27
  • 41
  • `snprintf()` writes to a char buffer. You need `wsnprintf()`. (Oh, and **turn on compiler warnings.**) –  Jan 19 '14 at 23:04
  • @BLUEPIXY it's not standard, but a common extension. it runs by various other names as well, such as `snwprintf()`. –  Jan 19 '14 at 23:11
  • this piece of code compiles in C mode with the warning like `warning C4133: 'function': incompatible types - from 'wchar_t [12]' to 'char *const '` for the line with the call of `snprintf`. If you change `a` into `char a[12]` and print it accordingly (like `printf("%s\n", a)`), then everything works as expected. – AntonK Jun 05 '23 at 16:24

4 Answers4

3

snprintf is for writing to char buffers. To write to a wchar_t buffer, you need swprintf instead.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
1

For an array T arr[10], sizeof arr returns the number of bytes occupied by the array (ie. sizeof(T) * 10 in this case.) However, swprintf expects the number of wchar_t in the destination buffer as its second argument.

The swprintf() function shall place output followed by the null wide character in consecutive wide characters starting at *ws; no more than n wide characters shall be written, including a terminating null wide character, which is always added (unless n is zero).

The below test code shows how the canary values are destroyed when you simply use sizeof a and the source wchar_t string is longer than the destination wchar_t buffer.

#include <wchar.h>
#include <stdio.h>

#define ARRLEN(a) (sizeof(a) / sizeof(a[0]))

int main() {
    struct S {
        int i;
        wchar_t a[4];
        int j, k, l;
    };
    struct S x = {}, y = {};
    wchar_t b[] = L"984567";
    int rcx, rcy;

    printf("Start\n");

    printf("%ld %ld\n", sizeof(x.a), sizeof(x.a[0]));

    rcx = swprintf(x.a, ARRLEN(x.a), L"%ls", b);
    rcy = swprintf(y.a, sizeof(y.a), L"%ls", b);

    printf("%#x %ls %#x %#x %#x %d\n", x.i, x.a, x.j, x.k, x.l, rcx);
    printf("%#x %ls %#x %#x %#x %d\n", y.i, y.a, y.j, y.k, y.l, rcy);
    printf("%ls\n", b);

    printf("end\n");
    return 0;
}
nodakai
  • 7,773
  • 3
  • 30
  • 60
  • Microsoft implements the _countof macro for this purpose: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/countof-macro?view=vs-2019 – Dan May 12 '20 at 15:20
0

Use swprintf.

#include <wchar.h>
#include <stdio.h>

int main()
{
    wchar_t a[ 10 ], b[] = L"984567";

    swprintf( a, sizeof( a ), L"%ls", b );

    printf("%ls\n", a);
}

Output: 984567

Mustafa Chelik
  • 2,113
  • 2
  • 17
  • 29
0

I know this is an old post, but I've done this method that returns a newline on windows. I stored the unicodes for "Carriage Return" and "Line Feed" inside a map, called _translator[] and then I created this function. This is a good example of how you can use swprintf.

wchar_t* NewLine() {
    wchar_t returning[2];
    swprintf(returning, sizeof(returning), L"%lc%lc", _translator[CARRIAGE_RETURN], _translator[LINE_FEED]);
    return returning;
}
  • bad piece of code: 1) `returning` is NOT large enough to zero-terminate the string properly; 2) returning pointer to a buffer on a stack – AntonK Jun 05 '23 at 16:12