The second line should read FILE *f = fmemopen(s, strlen(s), "r");
. As posted, fmemopen
has undefined behavior and might return NULL
, which causes getwc()
to crash.
Changing the fmemopen()
line and adding a check for NULL
fixes the crash but does not meet the OPs goal.
It seems wide orientation is not supported on streams open with fmemopen()
, At least for the GNU C library. Note that fmemopen
is not defined in the C Standard but in POSIX.1-2008 and is not available on many systems (like OS/X).
Here is a corrected and extended version of your program:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
int main(void) {
const char *s = "foo bar foo";
FILE *f = fmemopen((void *)s, strlen(s), "r");
wchar_t c;
if (f == NULL) {
printf("fmemopen failed: %s\n", strerror(errno));
return 1;
}
printf("default wide orientation: %d\n", fwide(f, 0));
printf("selected wide orientation: %d\n", fwide(f, 1));
while ((c = getwc(f)) != WEOF) {
printf("read %lc (%d 0x%x)\n", c, c, c);
}
return 0;
}
Run on linux:
default wide orientation: -1
selected wide orientation: -1
No output, WEOF
is returned immediately.
Explanation for fwide(f, 0)
from the linux man page:
SYNOPSIS
#include <wchar.h>
int fwide(FILE *stream, int mode);
When mode
is zero, the fwide()
function determines the current orientation of stream
. It returns a positive value if stream
is wide-character oriented, that is, if wide-character I/O is permitted but char I/O is disallowed. It returns a negative value if stream
is byte oriented, i.e., if char I/O is permitted but wide-character I/O is disallowed. It returns zero if stream
has no orientation yet; in this case the next I/O operation might change the orientation (to byte oriented if it is a char I/O operation, or to wide-character oriented if it is a wide-character I/O operation).
Once a stream has an orientation, it cannot be changed and persists until the stream is closed.
When mode
is nonzero, the fwide()
function first attempts to set stream
's orientation (to wide-character oriented if mode is greater than 0, or to byte oriented if mode
is less than 0). It then returns a value denoting the current orientation, as above.
The stream returned by fmemopen()
is byte-oriented and cannot be changed to wide-character oriented.