微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用write将整数和内存地址打印到控制台?

如何解决如何使用write将整数和内存地址打印到控制台?

我处于无法使用printf()打印到C语言控制台的情况。 这是大学的工作,我们正在重新实现malloc,calloc,free和realloc。我正在使用ubuntu,当我调用printf()时,由于printf()在其实现中使用malloc(根据我的讲师),它会隔离故障,所以我不能使用它,而必须使用{{1} }。

因此,如果我有一个简单的程序,如何使用write()打印一个整数和一个指向控制台的指针地址。

我尝试过:

write()

输出

#include <unistd.h>

int main(void) {
   int a = 12345;
   int* ptr = &a;
   
   // none of the following seem to work
   write(2,&a,sizeof(a));
   write(2,"\n",1);
   write(2,ptr,sizeof(ptr));
   write(2,&ptr,1);

   return 0;
}

谢谢,胡安

解决方法

  1. 确定要输出数字的格式。作为十六进制数字?小数?在八进制?在base64中?
  2. uintptr_t和字符串之间编写转换函数。 uintptr_t是可用于将指针转换为数字的类型。
  3. 将数字转换为字符串。
  4. 写字符串。

以下程序:

#include <unistd.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
char *uintptr_to_string(char *dest,size_t n,void *v0) {
    uintptr_t v = (uintptr_t)v0;
    for (int i = 0; i < sizeof(v) * 2; ++i) {
        if (n-- == 0) return NULL;
        const short idx = (v >> (sizeof(v) * CHAR_BIT - 4));
        const char hex[] = "0123456789abcdef";
        *dest++ = hex[idx];
        v <<= 4;
    }
    return dest;
}
int main() {
   char string[200];
   int a;
   char *end = uintptr_to_string(string,sizeof(string),&a);
   printf("%018p\n",(void*)&a);
   write(STDOUT_FILENO,"0x",2);
   write(STDOUT_FILENO,string,end - string);
   write(STDOUT_FILENO,"\n",1);
}

may output on godbolt

0x00007ffffd3d0a9c
0x00007ffffd3d0a9c
,

int12345等于0x0000003039(假设4字节int)。

在小端系统上(例如标准x86或x86-64 PC),它以序列0x39 0x30 0x00 0x00 0x00 0x00 0x00 0x00存储。

在ASCII编码中,0x39是字符'9',而0x30'0'

因此,打印值12345将打印两个字符90,然后打印一些不可打印的零。

您需要将值转换为 text 才能打印出来。也许像这样:

char value[128];

snprintf(value,sizeof value,"%d",a);
write(STDOUT_FILENO,value,strlen(value));

如果甚至不允许使用snprintf(或sprintf),则需要提出一些其他方法将数字转换为文本。

,

我处在无法使用printf()打印到C语言中的控制台的情况。这是大学的分配,我们正在重新实现malloc,calloc,free和realloc。我正在使用ubuntu

您很幸运。 Ubuntu主要是open source软件,

因此printfmalloc等的代码位于GNU glibc(或musl-libc)内部,其源代码(高于syscalls(2)由您可以阅读和学习Linux kernel)。

阅读Advanced Linux ProgrammingModern C(以及后来的C标准n1570)。

使用gdb(1)strace(1)了解您(或其他)程序的行为。

如果使用最新的GCC进行编译,请确保使用gcc -Wall -Wextra -g来获取DWARF调试器的警告和GDB调试信息。一旦您的代码正确无误,请add -O2进行编译器优化。如果您需要代码中的formal proof,请考虑使用Frama-C

在作业中提及您确实阅读过的源代码。您的老师将不胜感激。

当然,您需要将int a;转换为字符串缓冲区,例如char buf[80];避免使用buffer overflows和其他类型的undefined behavior 。您可能不被允许使用snprintf,但是您可以肯定地模仿它的代码和行为。将int转换为某些ASCII字符串很容易(假设您了解decimal number是什么)。

直觉是,对于包含0到9之间的小int x,它的ASCII十进制数字是(char)('0'+x)"0123456789"[x]。要转换更大的数字,请在一个简单的循环中巧妙地使用% modulus/整数除法运算符。

对于使用IBM ZEBCDIC个主要帧,应该相似。

完整的代码留给读者练习。

,

您需要将sizeof()乘以一个字节的大小

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?