【问题标题】:Write() gives weird symbols for integer [duplicate]Write() 为整数提供奇怪的符号 [重复]
【发布时间】:2019-02-26 23:39:42
【问题描述】:

我需要在信号处理函数中打印出一个字符串和一个整数。有人告诉我 write 是信号安全的。到目前为止,我已经尝试用 write 打印出一个整数,但它会发出奇怪的符号。 Write 适用于 char 字符数组,但不适用于整数。任何建议将不胜感激。下面是我的代码,它给出了错误。

    #include<stdio.h> 
    #include<wait.h> 
    #include<signal.h> 
    #include<unistd.h>
    int main() 
    { 
        int x[] = {100000};
        write(1, x, sizeof(x));
        return 0;
    }

【问题讨论】:

  • 你希望得到什么?
  • 如果您不了解数组内容和文件之间的关系,请使用十六进制编辑器查看文件和内存。内存内容不是用 ASCII 编码的(没有努力做到这一点),所以当你将它们直接转储到磁盘时,你不能指望文本表示。
  • 我只是将整数打印到控制台。
  • 100000 是十六进制的 000186a0。所以字节是00、01、86、a0。如果您的机器是 little-endian,那么它们会显示为 a0、86、01、00。前两个字符是非 ascii。你到底在期待什么?如果您想查看整数的文本表示,则首先需要将其转换为可打印的字符串。
  • write 打印原始字节,100000 的原始字节与字符串“100000”的原始字节不同。尽管 write 是异步信号安全的,但它不符合您将整数打印为字符串的其他重要要求。

标签: c linux


【解决方案1】:

当我编译你的程序并通过hexdump 重定向输出时,这是我得到的输出:

$ gcc t.c
$ ./a.out | hexdump
0000000 86a0 0001
0000004
$

然后,我们注意到十六进制的1000000x186a0。您的程序所做的是为表示数字 100000 的对象发出原始字节。

如果您想以 ASCII 格式将数字 100000 打印到输出,您可以编写自己的例程来执行此操作。例如:

void
print_number(unsigned x) {
    if (x >= 10) print_number(x/10);
    write(1, "0123456789" + (x%10), 1);
}

更好的方法是将转换后的字符发送到缓冲区,并在缓冲区文本上使用单个 write 调用,该缓冲区文本现在保存数字的字符串版本。

【解决方案2】:

这是构成内存中整数 100000 的字节,我已将其转换为十六进制:

A0 86 01 00

这是write(1, x, sizeof(x)) 打印的十六进制字节:

A0 86 01 00

这是printf("%d", x[0]) 打印的十六进制字节:

31 30 30 30 30 30

31(十六进制)是数字 1 的 ASCII 码,30 是数字 0 的 ASCII 码。但是 A0、87、01 和 00 是奇怪的符号。当您使用printf 时,它会将数字转换为专供人类阅读的内容; write 没有这种转换。

要以人们可以理解的方式将数字打印到控制台,请使用printf。但是您不应该在信号处理程序中使用printf,您说 - 这是正确的,因为您不应该在信号处理程序中写入控制台。 (如果您的信号处理程序在不同的写入过程中写入,可以吗?)

如果这只是一个测试,在信号处理程序中调用printf 可能就足够了,但它会时不时地崩溃,所以不要在你提供给其他人的程序中这样做。

【讨论】:

  • 感谢您的建议。但是我必须在信号处理程序中使用 write() 并且它不是可选的。这只是我项目的一部分。关于如何解决这个问题有什么建议吗?
  • 首先使用不同的函数将数字转换为十进制数字。比如snprintf。但我不确定 snprintf 是否也可以在信号处理程序中使用。
猜你喜欢
  • 1970-01-01
  • 2014-09-04
  • 2015-02-24
  • 1970-01-01
  • 1970-01-01
  • 2019-12-06
  • 2015-02-17
  • 1970-01-01
  • 2014-09-23
相关资源
最近更新 更多