【问题标题】:Order of printing with printf and my own print使用 printf 和我自己的打印的打印顺序
【发布时间】:2014-08-10 13:51:18
【问题描述】:

在我正在做的任务中,我需要创建自己的库,其中应该包含一个函数来打印字符串(prints)、打印整数(printi)并返回打印的字符数。该库应使用内嵌汇编语言编写(不使用任何 stdio.h 库)

问题是一切正常,但我无法理解 printfprinti 的调用顺序。

这是我的代码:

我自己的 myl 库:

/* 
 * print_int.c 
 * A system call to print an integer 
 */
#include "myl.h"  // my own library
#define BUFF 20

int printi(int n){  // my own printi function to print numbers
    char buff[BUFF], zero='0';
    int i=0, j, k, bytes;

    // saveN = n;
    if(n == 0) buff[i++]=zero;
    else{
        if(n < 0) {
            buff[i++]='-';
            n = -n;
        }
        while(n){
            int dig = n%10;
            buff[i++] = (char)(zero+dig);
            n /= 10;
        }
        if(buff[0] == '-') j = 1;
        else j = 0;
        k=i-1;
        while(j<k){
            char temp=buff[j];
            buff[j++] = buff[k];
            buff[k--] = temp;
        }
    } 
    // buff[i]='\n';
    bytes = i;

    __asm__ __volatile__ (
      "movl $4, %%eax \n\t"
      "movl $1, %%ebx \n\t"
      "int $128 \n\t"
      :
      :"c"(buff), "d"(bytes)
    ) ;  // $4: write, $1: on stdin

    return bytes;
}


int prints(char *str){  //my own prints function to print strings
    int i;
    for (i = 0; str[i]!='\0'; ++i) {}

  __asm__ __volatile__ (
    "movl $4, %%eax \n\t"
    "movl $1, %%ebx \n\t"
    "int $128 \n\t"
    :
    :"c"(str), "d"(i)
    ) ;  // $4: write, $1: on stdin
    return i;
}

还有我的 test.c 文件:

#include <stdio.h>
#include "myl.h"
int main()
{ 
    int n,k;
    char s[100];
    printf("Please enter a string: ");
    fflush(stdin);
    scanf("%[^\n]",s);
    k=prints(s);
    printf("\nNO of chars printed = ");

    printi(k);  // number of chars printed
    return 0;
}

一切正常,但在打印 NO of chars printed = 之前先打印 k..

这是终端显示的内容:

Please enter a string: asdf
asdf
4NO of chars printed =

我希望它是:

Please enter a string: asdf
asdf
NO of chars printed =4

那么订单有什么问题...?

【问题讨论】:

  • 从技术上讲,fflush(stdin) 是 C 中未定义的操作。某些平台支持将其作为扩展,但它不可移植。
  • 通常,在同一个文件上使用FILE *(如stdout)和文件描述符(如汇编程序中的1)不是一个好主意。或许可以通过调用write 来替换printf。 (假设您的评论有错字,应该是// $4: write, $1: on stdout。)
  • 次要:考虑使用char buff[sizeof(int)*CHAR_BITS/3 + 3] 来避免使用幻数20
  • @chux 对不起,我没看懂你的评论...... :(
  • 代码使用#define BUFF 20。为什么20特别?在您的系统上,20 似乎 足够大是一个“幻数”:它的出现毫无道理。通过使用诸如sizeof(int)*CHAR_BITS/3 + 3 之类的公式,所需的大小可以适应。如果int 是64 位整数,BUFF 将是24。如果int 是16 位,BUFF 将是8。如果int 是128 位,BUFF 将是45 .

标签: c assembly printf inline-assembly


【解决方案1】:

当 stdout 是终端时,printf() 默认会进行行缓冲。这意味着它不会调用实际的write() 系统调用,除非它看到\n 字符。所以你的printi() 首先打印,当程序退出时,字符串会从缓冲区中刷新。

您可能应该使用自己的非缓冲prints()

或者确实是fflush(stdout); 紧跟在printf 之后。

【讨论】:

    【解决方案2】:

    printf() 之后尝试fflush(stdout);。输出可能正在被缓冲。

    【讨论】:

      【解决方案3】:

      标准输出缓冲区可以被禁用调用:

      setbuf (stdout,NULL);
      

      在你的 main 的开头插入这个,允许混合标准输出和你的实现保持调用顺序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-15
        • 2010-11-05
        • 2018-06-04
        • 1970-01-01
        相关资源
        最近更新 更多