12

I know you should not mix printing with printf,cout and wprintf,wcout, but have a hard time finding a good answer why and if it is possible to get round it. The problem is I use a external library that prints with printf and my own uses wcout. If I do a simple example it works fine, but from my full application it simply does not print the printf statements. If this is really a limitation, then there would be many libraries out there which can not work together with wide printing applications. Any insight on this is more than welcome.

Update :

I boiled it down to :

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include <readline/readline.h>
#include <readline/history.h>

int main()
{
    char *buf;

    std::wcout << std::endl; /* ADDING THIS LINE MAKES PRINTF VANISH!!! */

    rl_bind_key('\t',rl_abort);//disable auto-complete

    while((buf = readline("my-command : "))!=NULL)
    {
        if (strcmp(buf,"quit")==0)
            break;

        std::wcout<<buf<< std::endl;

        if (buf[0]!=0)
            add_history(buf);
    }

    free(buf);

    return 0;
}

So I guess it might be a flushing problem, but it still looks strange to me, I have to check up on it.

Update -> Work around :

First of all, the same problem arise with wprintf. But I found that adding :

std::ios::sync_with_stdio(false);

actually did the trick...(note false and not as I would expect true..), the only thing that bothers me, is that I don't understand why and how to figure it out :-(

Bo Jensen
  • 638
  • 6
  • 13
  • I boiled it down to the following : #include #include #include #include #include int main() { char *buf; std::wcout << std::endl; /* ADDING THIS LINE MAKES PRINTF VANISH!!! */ rl_bind_key('\t',rl_abort);//disable auto-complete while((buf = readline("my-command : "))!=NULL) { if (strcmp(buf,"quit")==0) break; std::wcout< – Bo Jensen Apr 25 '10 at 15:36
  • sorry my mistake obviously not to be used with code snippets. – Bo Jensen Apr 25 '10 at 15:37
  • 2
    Why answers are focusing on mixing `cout` and `printf`, while the question is about mixing `cout` and `wcout`... – kennytm Apr 25 '10 at 15:49
  • No its not, because inside the readline function, there are printf statements. – Bo Jensen Apr 25 '10 at 15:57
  • @Kenny: Because the title doesn't make that clear. I'll try to improve it. – Ben Voigt Apr 25 '10 at 16:08
  • I can confirm that (in my case) mixing _tprintf and wcout crashes the application (written with Visual Studio 2010). Reproducibly. – Helge Klein Jun 01 '12 at 21:34

6 Answers6

7

I think you're talking about std::ios_base::sync_with_stdio, but IIRC it is on by default.

Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
6

You should be able to mix them, but they typically use separate buffering mechanisms so they overlap each other:

printf("hello world");
cout << "this is a suprise";

can result in:

hellothis is a suprise world

You don't provide enough information to diagnose your problem with printf() in your application, but I suspect you have more than one c runtime (one in your code, one in the printf() code) and there is a conflict.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Chris Hafey
  • 601
  • 3
  • 5
  • What I do is using GNU readline library for commandline history. So my application is linked with this library. – Bo Jensen Apr 25 '10 at 14:19
  • 1
    I might add, that if we talk about mixing cout and wcout (and not printf and wcout), then it is my experience it is not just scrambled out thats a problem, the application can crash. Thanks for your answer. – Bo Jensen Apr 25 '10 at 14:26
  • @Bo Jensen: That's not wcout's fault. That's your fault. Either that or there's a bug in your C++ standard library implementation. – Billy ONeal Apr 25 '10 at 14:48
  • 3
    This should be very unlikely, though. By default, cout and C's output streams should be syncronized (http://www.cplusplus.com/reference/iostream/ios_base/sync_with_stdio/). Output that in a loop for some 100 times and see what it outputs. Then turn of syncronization and try again. – UncleBens Apr 25 '10 at 14:58
4

The printf() and cout buffers are either synchronised by default, or are in fact the same buffer. If you are having problems with buffering, the obvious solution is to flush the buffer after each output:

fflush( stdout );
cout.flush();

this flushes the buffer(s) to the operating system, and once done there is no possibility of interleaving, or of output being lost.

0

buffering headaches. typically, you can, though, since they are synced. the people who tell you not to are probably people who remember the pain of using multiple io methods and want to save you from it. (just don't mix either with system calls. that would be painful.)

muhmuhten
  • 3,313
  • 1
  • 20
  • 26
0

Libraries should not use printf, cout, or any other I/O to standard handles. They should use a callback routine to delegate output to a method of the main program's choice.

An obvious exception is a library whose sole purpose is output, but then it's the main program's choice to use that. And this rule doesn't forbid I/O to file descriptors opened by the library.

Not only would that solve the issue raised here, but it also takes care of disconnected operation (linux program with no tty, eg run via nohup, or Win32 service).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

My opinion, not necessarily right, just for your reference. 😄


Overview

  • cout/wcout is the concept of the C++ world, the equivalence terms of C world is printf/wrpintf. These mechanisms are used to transfer our content that we provide in application into the standard output stream.
  • Compatible with C language is one of the C++' design objective. That is to say, the C++'s implementation must guarantee the mixing of C++ and C code execute correctly.
  • The problem is obvious, C and C++ are two different languages, after all. The C++'s cout/wcout and C's printf/wprintf have their own implementation, such as their own application layer buffer, their own flush strategy of the buffer, their own locale dependency ... At a word, cout/wcout and printf/wprintf are two separate operating mechanisms, simple mixing can lead to unexpected results, so the C++ standard designer must develop a workable solution.
  • From the coder's point of view, the correct behavior of mixing cout and printf should be guaranteed the execute result as like as just use cout or printf. To achieve this effect, the concept of sync with stdio is put forward. In my opinion, the 'stdio' refer in particular to the C language's I/O mechanism, printf/wprintf belong to it. So 'sync to stdio' means sync C++'s I/O mechanism to C's mechanism. We can use the method std::ios::sync_with_stdio to enable/disable the sync, it is enabled by default.
  • So, what is 'sync' indeed ? how to sync to stdio ? It depends on the implementation, I do not know the details. It seems that the 'sync' concept is more like 'share', the buffer of printf/wprintf shared with cout/wcout. Or the cout/wcout use print/wprintf's buffer directly. In brief, if we enable 'sync', the cout/wcout is no longer independent, typically the buffer, it depend on C stdio. The 'sync' makes the I/O process of C++ and C just like one language.
  • Therefore, we can use cout+printf or wcout+wprintf at ease in C++ code by enable sync with stdio (it's enabled by default, we don't need to operate). This problem is solved by 'sync'. The another puzzle is mix cout+wcout or mix printf+wprintf, is that ok ? -- this topic discuss below .
  • cout printf work on the char storage unit, and wcout wprintf work on wchar_t. Mixed use cout+wcout or printf+wprintf do not involve language level conflict. Because the cout wcout belong to same language, so do the printf and wprintf. The crux of the question here is 'the orientation of the standard output stream'.
  • What is the orientation mean? It can be interpreted as granularity i think. As we know, the OOD is object orientated design, that means the granularity of design is object. Another example is byte stream orientated protocol - TCP, that means we must concern the byte if we construct application based on TCP. Get in back to the point, so... what is the orientation of the standard output stream ? The answer is byte or wide byte or something else i don't confirm ...
  • The standard output stream either byte-oriented or wide byte-oriented, and how does the C++/C language determine which one? The strategy is to see the first executed I/O function/method's version, if it is the byte version, just like cout or printf, then the standard output stream is set to byte-oriented, else if it is the wide byte version, like wcout or wprintf, then the standard output stream is wide byte-oriented.
  • Why should we care the standard output stream oriented? That's because the different orientation of the standard output stream will affect the presentation of the content. It's easy to think of it this way, the orientation decide the granularity of the standard output stream to process/extract/translate the content from cout/wcout/printf/wprintf. Just think that, we first use wcout to trigger the standard output stream be set to wide byte-oriented, then we provide some content by cout, the result is the wide byte-oriented standard output stream received a group of content processed by byte, finally the content print to the device which connected to the standard output stream is undefined.
  • In addition, in my actual development, there's another situation of standard output stream orientation, i've discovered. After disable the sync witch stdio - std::ios::sync_with_stdio(false), no matter i call wcout then cout or call cout then wcout, the print content is all ok!(Of course, we must to set locale, but that's another topic). In this condition, i call fwide(stdout, 0) always return 0, that means the current standard output stream orientation is undecided, is the undecided state due to standard output stream can auto switch to suitable orientation? Or undecided means standard output stream in omnipotent state ? i don't know ...
  • A special case. There is a function called _setmode provided in Windows world, This function use for set the specific stream's translate mode. After my attempt, i guess the so called 'translate mode' is equivalent to the stream orientation. But, to use the _setmode set stream orientation seems to set some nonstandard flag value in underlying! Because after i call _setmode to set certain modes(e.g. _O_WTEXT, _O_U8TEXT, _O_U16TEXT ... ), if i call fwide try to check current stream orientation, the crash will happen. Perhaps an unintelligible data was queried by fwide, so it crashed!

Some demos

I write a function checkStdoutOrientation to get standard output stream orientation

void checkStdoutOrientation()                                                   
{                                                                               
    std::fstream fs("result.txt", std::ios::app);                               
    int ret = fwide(stdout, 0);                                                 
    if (ret > 0) {                                                              
        fs << "wide byte oriented\n";                                           
    } else if (ret < 0) {                                                       
        fs << "byte oriented\n";                                                
    } else {                                                                    
        fs << "undecided oriented\n";                                           
    }                                                                           
    fs.close();                                                                 
}    

Demo01: first call wcout, then call cout

#include <cstdio>                                                               
#include <iostream>                                                             
#include <fstream>  

int main()                                                                      
{                                                                               
    checkStdoutOrientation();                                                   
                                                                                
    std::wcout << "456" << std::endl;                                           
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    std::cout << "123" << std::endl;                                            
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    return 0;                                                                   
}          

debian10 buster + gcc 8.3.0

Output:
enter image description here

result.txt:
enter image description here

My understanding:

  • wcout is first called, so standard output stream is wide byte oriented;
  • just because the above situation, content processed by cout cannot be processed by standard output stream, so the "123" cannot print;

Win10 + vs2022

Output:
enter image description here

result.txt:
enter image description here

My understanding:

  • it seems that, the windows is not conforming to standards, the standard output stream is always undecided oriented;
  • just because the undecided oriented of the standard output stream, all content is print.

Demo02: first call cout, then call wcout

#include <cstdio>                                                               
#include <iostream>                                                             
#include <fstream>  

int main()                                                                      
{                                                                               
    checkStdoutOrientation();                                                   
                                                                                
    std::cout << "123" << std::endl;                                            
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    std::wcout << "456" << std::endl;                                           
                                                                                
    checkStdoutOrientation();

    return 0;
} 

debian10 buster + gcc 8.3.0

Output:
enter image description here

result.txt:
enter image description here

My understanding:

  • cout is first called, so standard output stream is byte oriented;
  • because byte is a smaller granularity than wide byte, so wcout content to byte oriented standard output stream can finally print to console.

Win10 + vs2022

Output:
enter image description here

result.txt:
enter image description here

My understanding:

  • the standard output stream is always undecided oriented;
  • so all content is print.

Demo03: first call wprintf, then call printf

#include <cstdio>                                                               
#include <iostream>                                                             
#include <fstream>  

int main()                                                                                                                                                                                                       
{                                                                               
    checkStdoutOrientation();                                                   
                                                                                
    wprintf(L"456\n");                                                          
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    printf("123\n");                                                            
                                                                                
    checkStdoutOrientation();                                                 
                                                                                
    return 0;                                                                   
}          

It's the same conclusion as Demo01

Demo04: first call printf, then call wprintf

#include <cstdio>                                                               
#include <iostream>                                                             
#include <fstream>  

int main()                                                                      
{                                                                               
    checkStdoutOrientation();                                                   
                                                                               
    printf("123\n");                                                                                                    
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    wprintf(L"456\n");                                                          
                                                                                
    checkStdoutOrientation();

    return 0;
} 

debian10 buster + gcc 8.3.0

Output:
enter image description here

result.txt:
enter image description here

My understanding:

  • cout is first called, so standard output stream is byte oriented;
  • the result is different from Demo02, i don't know why the "456" not show.

Win10 + vs2022

Output:
enter image description here

result.txt:
enter image description here

My understanding:

  • the same result as Demo02 .

Demo05: disable sync with stdio, then wcout, cout

#include <cstdio>                                                               
#include <iostream>                                                             
#include <fstream>  

int main()                                                                      
{                                                                               
    std::ios::sync_with_stdio(false);                                           
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    std::wcout << "456" << std::endl;                                           
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    std::cout << "123" << std::endl;                                            
                                                                                
    checkStdoutOrientation(); 

    return 0;
} 

debian10 buster + gcc 8.3.0

Output:
enter image description here

result.txt:
enter image description here

My understanding:

  • after disabled sync with stdio, the standard output stream is always undecided oriented;
  • so all content can print.

Win10 + vs2022

Output:
enter image description here

result.txt:
enter image description here

My understanding:

  • the same result as Demo01 .

Demo06: mix cout, printf

#include <cstdio>                                                               
#include <iostream> 

int main()                                                                      
{                                                                               
    printf("1\n");                                                              
    std::cout << "2\n";                                                         
    printf("3\n");                                                              
    std::cout << "4\n";                                                         
    printf("5\n");                                                              
                                                                                
    printf("\n");                                                               
                                                                                
    std::ios::sync_with_stdio(false);                                           
                                                                                
    printf("1\n");                                                              
    std::cout << "2\n";                                                         
    printf("3\n");                                                              
    std::cout << "4\n";                                                         
    printf("5\n");                                                              
                                                                                                                                                        
    return 0;                                                                   
}   

debian10 buster + gcc 8.3.0

Output:
enter image description here

My understanding:

  • sync with stdio is enabled default, so mix cout and printf worked as just call cout or printf.
  • after disabled sync with stdio, cout will worked independent, cout and printf do their own thing, so the print content is out of order.

Win10 + vs2022

Output:
enter image description here

My understanding:

  • Windows is still so special, no matter disable sync with stdio or not, the mix cout and printf worked as just call cout or printf.

Demo07: print Non-ASCII Characters -- Method A

#include <cstdio>                                                               
#include <iostream>                                                             

int main()                                                                      
{                                                                               
    std::locale myloc("en_US.UTF-8");                                           
    std::locale::global(myloc); // this setting does not affect wcout                                         
                                                                                
    std::wcout << L"漢字\n";  
    wprintf(L"漢字\n");                                                         

    return 0;
} 

debian10 buster + gcc 8.3.0

Output:
enter image description here

My understanding:

  • set global locale does not affect wcout, this wcout's locale is still C locale. It is because the wcout is an object, its locale has already set when object constructed.
  • so in that case, why wcout can print the content? don't forget the C++'s iostream is default sync with the stdio, we can simply think that, the wcout work on stdio's buffer, and the stdio is already set to en_US.UTF-8 by the global(myloc) code.

Win10 + vs2022

Output:
enter image description here

My understanding:

  • nothing special;

Demo08: print Non-ASCII Characters -- Method B

#include <cstdio>                                                               
#include <iostream>                                                             

int main()                                                                      
{                                                                               
    std::ios::sync_with_stdio(false);                                           
                                                                                
    std::locale myloc("en_US.UTF-8");                                           
    // std::locale::global(myloc);                                              
                                                                                
    std::wcout.imbue(myloc);                                                    
    std::wcout << "wcout> " << L"漢字\n";                                       
    wprintf(L"wprintf> 漢字\n");                                                         

    return 0;
} 

debian10 buster + gcc 8.3.0

Output:
enter image description here

My understanding:

  • due to disabled sync to stdio, the wprintf and wcout work separately, so print out of order;
  • Still due to the sync disabled, wcout should work independent, so we must set wout's locale to en_US.UTF-8 by imbue method, if not do this, the wcout will print content like "??";
  • wprintf print "??", that's because we commented out the std::locale::global(myloc);, so the locale for stdio is still C locale.

Win10 + vs2022

Output:
enter image description here

My understanding:

  • printf and cout print always in order, this is the windows special place, this has been mentioned several times;
  • wprintf print empty is equivalent to the "??" in linux;
  • so, what's new is the garbled code! i try to uncomment the std::locale::global(myloc); code, the print content is ok! so, i think the windows implemention is little special, the wcout may depend on more things that need change locale by global locale setting.

Demo09: print Non-ASCII Characters -- Method C

This demo depends on the windows platform .

#include <cstdio>                                                               
#include <iostream>                                                             

int main()                                                                      
{                                                                               
    _setmode(_fileno(stdout), _O_WTEXT); // Unique function to windows 

    std::wcout << "wcout> " << L"漢字\n";
    wprintf(L"wprintf> 漢字\n");                                                  

    return 0;
} 

Win10 + vs2022

Output:
enter image description here

My understanding:

  • after _setmode, the globale and wcout locale is still C locale;
  • why wcout and wprintf all can print content correctly? i guess maybe the windows implement a mechanism after standard output stream to translate the content by the _setmode specified mode.
name-1001
  • 120
  • 2
  • 4