Компилиране с TCC на Cygwin

Тествах много проста програма, написана на C, цялата която е приложена по-долу. При опит да изпълня изпълнимия файл, произведен от TCC, забелязах, че трябваше да въвеждам вход за всеки следващ fgets(), преди действително да видя изход от извиквания на printf().

Това беше много объркващо, така че реших да опитам да стартирам изпълнимия файл на стандартната конзола на Windows. Работеше безупречно и подканите за въвеждане и извеждане бяха показани в правилния ред.

Забелязах обаче, че ако компилирах програмата с GCC, тя щеше да работи добре на терминала, компилиран в Cygwin (mintty, въпреки че получих същите резултати с rxvt).

Може ли някой да даде обяснение защо се случва това и как мога да го спра? Бих искал да компилирам програмите си независимо от Cygwin, докато все още използвам терминал, базиран на Cygwin.

Благодаря!

int main()
{
        char something[12];

        printf("This printf() should be outputted before you are prompted for input: ");

        fgets(something, sizeof something, stdin);

        printf("You entered, %s", something);
}

person Jonathan Chan    schedule 23.04.2011    source източник


Отговори (3)


Mintty и rxvt са терминални емулатори, базирани на Unix псевдо терминални устройства. Cygwin прилага тези въз основа на тръби на Windows.

Когато компилирате програма с Cygwin gcc, тя се свързва с Cygwin DLL, който съдържа цялата магия, за да накара потоците, свързани към терминал, да работят както трябва в Unix система, което означава буфериране на линии по подразбиране.

Въпреки това, когато компилирате програмата с tcc, вие създавате родна програма за Windows и тя вижда само основните канали на Windows. В библиотеката на Microsoft C потоците, свързани с канали, са напълно буферирани по подразбиране, поради което изричното изчистване с fflush(stdout) или деактивирането на буферирането с setvbuf(stdout, NULL, _IONBF, 0) помага. C библиотеката на MS не поддържа буфериране на линии.

person ak2    schedule 23.04.2011
comment
От всички отговори реших, че този има най-подробното обяснение, поради което го избрах като най-добрия отговор. Благодаря на всички! - person Jonathan Chan; 24.04.2011

Това се свежда до буферирането на стандартния вход и стандартния изход. Не съм сигурен какво има да каже стандартът C за това (в C++ потоците са свързани по подразбиране), но можете сами да изчистите стандартния изход с:

 fflush( stdout );

след извикването на printf.

person Community    schedule 23.04.2011

Стандартният изходен поток обикновено е редово буфериран, т.е. буферът се изчиства, когато отпечатате нов ред.

Можете да го изчистите изрично с:

fflush(stdout);

И можете да изключите буферирането за даден поток s с:

setvbuf(s, NULL, _IONBF, 0);

Вижте man страницата на setvbuf() за повече подробности.

person Philip    schedule 23.04.2011
comment
По подразбиране stdout е буфериран на линия, когато е изпратен към терминал, и е напълно буфериран, когато е изпратен към нещо друго (тръба, сокет, файл и т.н.) За сравнение, stderr не е буфериран по подразбиране (тъй като се използва за запис на информация, която може да диагностицира защо се случва срив, потенциално преди буферите да бъдат изчистени автоматично). - person Donal Fellows; 23.04.2011
comment
@Donal Да, това казва стандартът и това е и това, което Cygwin прилага, но не и библиотеката на Microsoft C. Там както stdout, така и stderr са дебуферирани, когато са свързани към конзола, и напълно буферирани, когато са свързани към файл или тръба. Буферирането на линията не се поддържа. - person ak2; 23.04.2011
comment
@ak2: Ето защо не го предлагах като решение. MS раздухването на още една част от C библиотеката едва ли е изненадващо... - person Donal Fellows; 24.04.2011