【问题标题】:printf output always before scanf, who can give a solution?printf输出总是在scanf之前,谁能给出解决方案?
【发布时间】:2022-01-15 10:44:52
【问题描述】:

谁知道打印顺序错误的根本原因? 如何解决? 我将以下代码编译为汇编:

{
    int a, b;

    sprint("input number\n");
    scan  (a);
    iprint(a);
}

这生成了以下汇编代码:

    IO:
    .string "%lld\n"
    .text
    .globl main
main:
    pushq %rbp
    movq %rsp, %rbp
    subq $32, %rsp
    .data
L1: .string "input number"
    .text
    leaq L1(%rip), %rcx
    movq $0, %rax
    subq $32, %rsp
    callq printf             <-------printf
    addq $32, %rsp
    movq %rbp, %rax
    leaq -8(%rax), %rax
    movq %rax, %rdx
    leaq IO(%rip), %rcx
    subq $32, %rsp
    callq scanf             <---------scanf
    addq $32, %rsp
    movq %rbp, %rax
    leaq -8(%rax), %rax
    movq (%rax), %rax
    pushq %rax
    popq  %rdx
    leaq IO(%rip), %rcx
    subq $32, %rsp
    callq printf            <--------printf
    addq $32, %rsp
    leaveq
    retq

我在windows 7上安装了Embarcadero-dev-cpp,使用gcc tmp.s得到一个执行文件a.exe,然后运行a.exe

$ ./a.exe
987                 <-----my input, should be the second display
input number        <-------should be print firstly
987                 <-------the last.
jason@jason-PC ~/samplecygwin
$

printf、scanf的阳离子顺序不对。

我的高级语言代码被翻译成汇编代码。 我应该在编译器中的 printf 之后插入 flush(stdout) 吗? 谢谢你。 这是一个常见的问题,但很少遇到,请参考以下内容。

scanf before printf - C

printf before scanf doesn't show printf string before input

Scanf executed before printf in Eclipse

【问题讨论】:

  • sprintscaniprint的定义是什么?
  • 我认为您没有编写编译器。您可能编写了一个程序并编译了它;-)。顺便说一句,看到一个完整的程序对我们总是有帮助的,最好归结为一个最小的例子。
  • @Peter-ReinstateMonica:在call scanf system subroutine to input a integer number but error in the execute 中,询问者说他们的教授 编写了一个编译器,ed.tus.ac.jp/j-mune/ccp。这种极度臃肿的 asm 用玩具编译器比手写更容易解释,例如movq %rbp, %rax / leaq -8(%rax), %rax / movq %rax, %rdx 而不是 lea -8(%rbp), %rdx

标签: assembly output printf scanf


【解决方案1】:

这通常是因为输出缓冲:printf 调用按预期发生(正如您通过查看生成的汇编程序验证的那样)但屏幕上没有显示任何内容:它全部进入某个缓冲区并耐心等待直到已经积累了一些输出数据,值得暂停程序并调用操作系统例程。典型的缓冲区大小为 4096 字节。您可以通过将 4096(或者可能是 4097)字符写入标准输出来验证这一理论,或者如果这不起作用,则使用 2 的下一个幂,直到出现某些情况。

旁注:在普通终端上scanf 会自动导致标准输出的刷新,以避免这种情况。也许 Embarcadero(这是一个面向 GUI 的 IDE)将输入和输出用于无法识别为终端的控制台程序,因此这不起作用。出于好奇,您可以尝试找出可执行文件的位置,打开一个普通的 Windows 控制台,然后根据命令行直接执行您的程序。如果它按预期工作,我不会感到惊讶。

您可以对您的程序做些什么来使其在 Embarcadero 中正常工作?每次你想在屏幕上看到输出时,你可以fflush()stdout,或者调用一次setbuf(),然后一切都会显示出来。

但是,您是否应该因为一个行为不端的开发环境而使您的程序变得混乱,这是值得商榷的。如果您可以通过常规控制台按原样成功运行它,我宁愿这样做。

【讨论】:

  • fprintf to stderr 将是另一种解决错误环境的方法,尽管我认为在标准输出上打印交互式提示更正常,对于提示和读取标准输入而不是采取的程序命令行参数。
  • @PeterCordes 在两个方面都是正确的,我会说;-)。作为一种解决方法,在 stderr 上进行交互似乎比刷新/setbuffing stdout 更糟糕。
猜你喜欢
  • 2012-11-24
  • 1970-01-01
  • 2020-07-15
  • 2021-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多