printf and wprintf in single C code
Asked Answered
H

2

28

I have a problem when using printf and wprintf functions together in code. If the regular string is printed first, then wprintf doesn't work. If I use wprintf first then printf doesn't work.

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

int main() 
{
    setlocale(LC_ALL,"");

    printf("No printing!\n");
    wprintf(L"Printing!\n");
    wprintf(L"Wide char\n");
    printf("ASCII\n");
    return 0;
}

Outputs:

No printing!
ASCII

While

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

int main() 
{
    setlocale(LC_ALL,"");

    wprintf(L"Printing!\n");
    printf("No printing!\n");
    wprintf(L"Wide char\n");
    printf("ASCII\n");
    return 0;
}

outputs:

Printing!
Wide char

I'm using gcc (GCC) 4.6.1 20110819 together with glibc 2.14 on 64bit Linux 3.0.

Halfandhalf answered 30/12, 2011 at 16:28 Comment(2)
Linux 3.0? What's that? What distribution?Pushed
@bmargulies: Kernel version. Distribution is Archlinux.Halfandhalf
S
26

This is to be expected; your code is invoking undefined behavior. Per the C standard, each FILE stream has associated with it an "orientation" (either "byte" or "wide) which is set by the first operation performed on it, and which can be inspected with the fwide function. Calling any function whose orientation conflicts with the orientation of the stream results in undefined behavior.

Slosh answered 30/12, 2011 at 17:10 Comment(9)
Is is undefined behavior or simply outputting nothing if the orientation mismatches the data to be written?Rawdon
Based on this: gnu.org/savannah-checkouts/gnu/libc/manual/html_node/…, the behavior is undefined.Persis
@Rawdon Undefined behavior means there are no expectations for how it should behave in this circumstance. Therefore, outputting nothing is acceptable, as is silently converting the text to the proper orientation or printing garbage.Eon
@DRH: Thanks! " ... The application behavior will simply be strange or the application will simply crash.... " at least the "or" in this lets me tend to understand that things seem to be somehow "undefined" ... ;-)Rawdon
@Hubert: it's not a bug in the man page. kernel.org/doc/man-pages/online/pages/man3/wprintf.3.html says: "stdout must not be byte oriented"Sometime
Is it possible to reopen stdout and change the orientation?Ruth
freopen can clear the orientation, but it also has drawbacks. See POSIX on the matter: pubs.opengroup.org/onlinepubs/9699919799/functions/freopen.html particularly the "Application Usage" section.Slosh
@Andreyua: There is no proper way. You just need to avoid doing this.Slosh
@R..GitHubSTOPHELPINGICE So we either use printf() or wprintf()? One or the other...Stedfast
C
5

To complement R..'s accepted answer:

While this is very rarely done, checking the return code of printf/wprintf would more clearly indicate that one of them is not working (it should return -1 for the print function which is invalid according to the current orientation of the stream).

Unfortunately, a common pattern for checking errors in standard library functions:

if (wprintf(...) == -1) { perror("wprintf"); ... }

May not help much here: if the stream is set to output non-wide characters, and you call wprintf, errno may not be set and you'll get wprintf: Success, which does not provide much information.

So indeed this is a somewhat hard to understand issue when you don't know about the character orientation of streams.

Collayer answered 2/3, 2015 at 15:11 Comment(1)
Checking the return value helps when you have a reportable error, not when you have undefined behavior. wprintf is not specified to fail when the orientation is wrong. Rather, what it does when the orientation is wrong is not specified at all. That's what undefined means.Slosh

© 2022 - 2024 — McMap. All rights reserved.