【问题标题】:C: Write the address of a pointer on the standard output?C:在标准输出上写一个指针的地址?
【发布时间】:2017-02-26 12:12:48
【问题描述】:

如何仅使用write() 函数将指针的地址写入标准输出。 (类似于printf() 函数中的%p 标志。)

我不能使用除“write”“malloc”和“free”以外的任何东西。

【问题讨论】:

  • 只有写功能?不能使用sprintf 之类的东西来准备输出?
  • 您是否尝试过使用snprintf?如果有,进展如何?如果没有,试试吧!如果不能使用,那么需要使用一些其他的(可能是你自己的)函数将数字转为字符串,但原理是一样的。
  • 我不能使用除write mallocfree 之外的任何东西。
  • 这是实现定义的。它不能以便携的方式完成。但是第一步你应该看看uintptr_t。其余的主要是你应该在课程中学习的整数算术。

标签: c pointers memory-address


【解决方案1】:

如果您尝试重新编码printf,您可能想要实现%p。使用以下步骤:

  • 从参数 va_list 中检索指针的值。
  • 将该指针转换为uintptr_t 或任何适合目标架构指针大小的无符号整数类型。
  • 将此整数转换为带有0x 前缀的十六进制格式字符串,与%#x 格式一样。
  • 将结果字符串写入输出文件。

【讨论】:

  • uintptr_t 是唯一保证保存指针值的类型。但是除了分配给/从相同的void *(以及间接地其他指针类型)之外的任何其他内容都是特定于实现的。输出格式也是如此(他也可以将字节打印为字符)。
【解决方案2】:

如果你有一个像char *p; 这样的指针变量,那么你可以使用

write(filedescriptor, &p, sizeof(p));

就像真的写任何其他变量一样。

如果要写成字符串,那么需要先格式化成字符串,再写成字符串:

char pstr[sizeof(p) * 2 + 2 + 1]; // Each byte of the pointer is two hexadecimal character, plus a potential 0x, plus terminator
snprintf(pstr, sizeof(pstr), "%p", (void *) p);
write(filedescriptor, pstr, strlen(pstr));

可以使用 only write 将其写为字符串,将指针视为普通整数值,并循环遍历指针变量中的所有字节并使用模和除法或移位来获取每个字节,然后使用字节掩码和移位来获取每个字节的每个半字节,并将其转换为要写入的字符。如果将指针值复制到字节数组中进行迭代可能会更容易,因为您不必进行模/除,只需进行掩码和移位即可获得每个半字节。


但是话虽如此,我真的很好奇为什么你会想要这样的东西?因为您不能将指针保存在文件中并在另一个程序中使用它(甚至是同一个程序但作为新进程运行),所以您不能通过管道或套接字将它发送到另一个进程。

【讨论】:

  • sizeof(p) * 2 + 1 可能没有足够的空间用于%p 生成的指针值的文本表示。 0x 前缀经常出现,并且该标准为实现做出架构特定选择留下了很大的空间。您应该声明一个更大的缓冲区并使用snprintf 以避免潜在的缓冲区溢出。
  • @chqrlie 你说得对,我应该从一开始就使用snprintf
  • 正如我刚刚在问题的编辑中提到的,除了编写 malloc 和 free 之外,我不能使用其他任何东西。您给write(filedescriptor, &p, sizeof(p)); 的第一个解决方案似乎不起作用。我得到�'��� 作为输出。
  • @CosminSerdean 已经添加了解决方案(snprintf 示例下的段落)。
  • “就像真正编写任何其他变量一样”是虚假的——编写未编组的二进制文件通常是灾难的根源。至于“为什么”:出于同样的原因,%p 在后来的 C 标准迭代中被引入。
猜你喜欢
  • 1970-01-01
  • 2014-07-23
  • 2013-05-17
  • 1970-01-01
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
  • 2012-01-25
  • 1970-01-01
相关资源
最近更新 更多