了解sprintf如何将整数转换为字符串

时间:2019-03-20 16:16:42

标签: c printf

我正在学习C,并且正在学习一个将整数转换为字符串的基本示例(您认为这是其他语言的前提)。我找到的答案是这样:

sprintf(str, "%d", num);

但是我想看看这是如何实现的。所以我抬起头来sprintf,把我带到这里:

#define vsprintf(s, f, a) _IO_vsprintf (s, f, a)

int
__sprintf (char *s, const char *format, ...)
{
  va_list arg;
  int done;

  va_start (arg, format);
  done = vsprintf (s, format, arg);
  va_end (arg);

  return done;
}

因此,我向上看_IO_vsprintf,它显示:

int
__IO_vsprintf (char *string, const char *format, va_list args)
{
  _IO_strfile sf;
  int ret;

#ifdef _IO_MTSAFE_IO
  sf._sbf._f._lock = NULL;
#endif
  _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
  _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
  _IO_str_init_static_internal (&sf, string, -1, string);
  ret = _IO_vfprintf (&sf._sbf._f, format, args);
  _IO_putc_unlocked ('\0', &sf._sbf._f);
  return ret;
}

似乎围绕_IO_vfprintf。但是我找不到code中的位置。 Google和GitHub没有任何结果。想知道是否有人可以使用sprintf的完整实现,如果没有,可以解释它的工作原理。

我想知道如何像sprintf一样实现itoa,这听起来像是一个很好的实现。

对于没有实现的情况,该代码如何实际运行感到困惑。

1 个答案:

答案 0 :(得分:2)

Looks(例如_IO_vfprintf)是_IO_vfprintf_internal的隐藏别名。

在编译文件vfprintf.c中的普通(不宽字符)文件时,fprintf变成一个宏,定义为_IO_vfprintf_internal,从here开始,并且在别名{{ 3}}。

因此_IO_vfprintf_internal声明从here开始,在此声明vfprintf(好吧,“在未经处理的源文件中”,标识符vfprintf从未声明)。 / p>

vfprintf函数停止处理所有宽度,空格,负号和其他格式说明符之后,它最终将跳过here(这基本上是一种跳到不同{{1 }}(由跳转表标记),该跳转表具有通过GCC扩展名jump tables获得的地址),它将落在labels as values标签上。从那里我们form_integer:jump。从那里我们叫number:

现在_itoa_word很简单,甚至足以在此处发布预处理功能:

goto

其中char * _itoa_word (_ITOA_WORD_TYPE value, char *buflim, unsigned int base, int upper_case) { const char *digits = (upper_case ? _itoa_upper_digits : _itoa_lower_digits); ... switch (base) { ... // SPECIAL (10); expands to: case 10: do *--buflim = digits[value % Base]; while ((value /= Base) != 0); break; ... } ... } (如_itoa_word_itoa_upper_digits)是一个简单的查找表,是从字符串文字中初始化的char数组,用于将小数转换为相关的ascii表示形式

digits之后,有一些代码用于处理字符串的左对齐,打印前导符号字符并用空格或零填充字符串,但最终我们的字符串为_itoa_lower_digits(或左对齐的{{3 }}。

  

将整数转换为字符串的示例

所以99%的工作是处理所有奇怪的事情

_itoa_word

它需要符合的格式说明符。转换只是使用查找字符串(以处理非ASCII系统)的简单转换,可以通过数字向后查找:

printf("%+- 3lld %+- 4.3Lf %-+04hhd %+- 5zd", 1llu, 2.L, 3, (ssize_t)4);