# \[Bug #6\] sprintf() of %f on Windows(MSVCRT)

**URL:** <https://www.ruby-forum.com/t/bug-6-sprintf-of-f-on-windows-msvcrt/151810>\
**Category:** Development\
**Created:** [October 26, 2008, 2:36am UTC](https://www.ruby-forum.com/t/bug-6-sprintf-of-f-on-windows-msvcrt/151810 "2008-10-26T02:36:02Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![SSwanabe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/d6d6ee/32.png) [@SSwanabe](https://www.ruby-forum.com/u/SSwanabe)\
**Post date:** [October 26, 2008, 2:36am UTC](https://www.ruby-forum.com/t/bug-6-sprintf-of-f-on-windows-msvcrt/151810/1 "2008-10-26T02:36:02Z")

</div>

e$B%A%1%C%He(B #6 e$B$,99?7$5$l$^$7$?!#e(B (by \_ wanabe)

e$B%U%!%$%ke(B sprintf.patch e$BDI2Ce(B

## missing/vsnprintf.c e$B$rMxMQ$9$k$h$&$J%Q%C%A$r=q$-$^$7$?!#e(B vsnprintf.c e$BCf$Ne(B vsnprintf e$B$r30$K=P$9$d$jJ}$,$“$^$j$&$^$/$J$$$h$&$K;W$&$N$Ge(B e$B2?$+$&$^$$J}K!$r$4B8CN$NJ}$O65$($F$$$?$@$1$k$H$”$j$,$?$$$G$9!#e(B

[http://redmine.ruby-lang.org/issues/show/6](http://redmine.ruby-lang.org/issues/show/6)

---

<div class="post-metadata">

**Author:** ![SSwanabe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/d6d6ee/32.png) [@SSwanabe](https://www.ruby-forum.com/u/SSwanabe)\
**Post date:** [October 26, 2008, 7:46am UTC](https://www.ruby-forum.com/t/bug-6-sprintf-of-f-on-windows-msvcrt/151810/2 "2008-10-26T07:46:56Z")

</div>

e$B$J$+$@$G$9!#e(B

At Sun, 26 Oct 2008 10:35:17 +0900,  
\_ wanabe wrote in [ruby-dev:36932]:

> vsnprintf.c e$BCf$Ne(B vsnprintf e$B$r30$K=P$9$d$jJ}$,$"$^$j$&$^$/$J$$$h$&$K;W$&$N$Ge(B  
> e$B2?$+$&$^$$J}K!$r$4B8CN$NJ}$O65$($F$$$?$@$1$k$H$"$j$,$?$$$G$9!#e(B

win32/Makefile.sube$B$Ne(BHAVE\_VSNPRINTFe$B$r\>C$;$Pe(Bmissinge$B$N$[$&$r;H$&$he(B  
e$B$&$K$J$k$O$:$G$9!#e(B

e$B$A$J$\_$K!"e(Bmissing/vsnprintf.ce$B$X$N=$@5$O$I$&$$$&$b$N$G$7$g$&$+!#e(B

---

<div class="post-metadata">

**Author:** ![SSwanabe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/d6d6ee/32.png) [@SSwanabe](https://www.ruby-forum.com/u/SSwanabe)\
**Post date:** [October 26, 2008, 2:38pm UTC](https://www.ruby-forum.com/t/bug-6-sprintf-of-f-on-windows-msvcrt/151810/3 "2008-10-26T14:38:23Z")

</div>

e$B$J$+$@$G$9!#e(B

At Sun, 26 Oct 2008 20:42:54 +0900,  
wanabe wrote in [ruby-dev:36935]:

> > win32/Makefile.sube$B$Ne(BHAVE\_VSNPRINTFe$B$r\>C$;$Pe(Bmissinge$B$N$[$&$r;H$&$he(B  
> > e$B$&$K$J$k$O$:$G$9!#e(B
> 
> mingw e$B$G$Oe(B configure e$B$G@8@.$5$l$?e(Bconfig.h e$B$r;H$&$h$&$G$9$7e(B  
> bcc e$B$G$Oe(B msvcrt e$B$r;H$o$J$$$h$&$J$N$G!"$=$l$O:G8e$N\<jCJ$K$7$?$$$H;W$$$^$9!#e(B

mingwe$B$G$Oe(Bconfiugre.ine$B$Ne(B ac\_cv\_func\_vsnprintf=yes  
e$B$H$$$&9T$r\>C$;e(B  
e$B$P$G$-$k$O$:$G$9!#e(Bbcce$B$Oe(Bbcc32/Makefile.sube$B$K$"$kDj5A$r;H$&$N$G!"e(B  
win32/Makefile.sube$B$rJQ99$7$F$b1F6A$O\<u$1$^$;$s!#e(B

> e$B$G$9$,%"%I%P%$%9$N$\*$+$2$G$&$^$/$$$+$J$$860x$,$o$+$j$^$7$?!#$"$j$,$H$&$4$6$$$^$9!#e(B  
> vsnprinte$B#fe(B e$B$re(B rb\_win32\_vsnprintf e$B$G\>e=q$-$7$J$1$l$P$$$$$@$1$@$C$?$h$&$G$9!#e(B

rb\_w32\_vsnprintf()e$B$Oe(Bmsvcrte$B$Ne(Bvsnprintf()e$B$N%P%0$r2sHr$9$k$?$a$N$be(B  
e$B$N$J$N$G!“e(Bmissinge$B$N$b$N$r;H$&$N$G$”$l$Pe(Bsnprintf()e$B$bITMW$K$J$j$^e(B  
e$B$9!#%P%$%J%j8\_49$K$D$$$F$Oe(Bwin32/mkexports.rbe$B$Ge(Baliase$B$7$F$\*$1$P=\<e(B  
e$BJ,$G$7$g$&!#e(B

> > e$B$A$J$\_$K!"e(Bmissing/vsnprintf.ce$B$X$N=$@5$O$I$&$$$&$b$N$G$7$g$&$+!#e(B
> 
> e$B@bL@ITB-$G$7$?!#$9$\_$^$;$s!#e(B  
> test\_sprintf\_comb.rb e$B$,DL$k$h$&$K=$@5$7$^$7$?!#6qBNE\*$K$O0J2\<$NDL$j$G$9!#e(B

e$B$J$k$[$I!#e(B

> - sprintf(buf, “%#.15g”, value); /\* ensure to print decimal point \*/
> 
> - snprintf(buf, 32, “%#.15g”, value); /\* ensure to print decimal point \*/

sizeof(buf)e$B$N$[$&$,$$$$$H;W$$$^$9!#e(B

---

<div class="post-metadata">

**Author:** ![SSwanabe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/d6d6ee/32.png) [@SSwanabe](https://www.ruby-forum.com/u/SSwanabe)\
**Post date:** [October 26, 2008, 12:44pm UTC](https://www.ruby-forum.com/t/bug-6-sprintf-of-f-on-windows-msvcrt/151810/4 "2008-10-26T12:44:12Z")

</div>

e$B%o%J%Y$G$9!#e(B

2008/10/26 15:45 Nobuyoshi N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> At Sun, 26 Oct 2008 10:35:17 +0900,  
> \_ wanabe wrote in [ruby-dev:36932]:
> 
> > vsnprintf.c e$BCf$Ne(B vsnprintf e$B$r30$K=P$9$d$jJ}$,$“$^$j$&$^$/$J$$$h$&$K;W$&$N$Ge(B  
> > e$B2?$+$&$^$$J}K!$r$4B8CN$NJ}$O65$($F$$$?$@$1$k$H$”$j$,$?$$$G$9!#e(B
> 
> win32/Makefile.sube$B$Ne(BHAVE\_VSNPRINTFe$B$r\>C$;$Pe(Bmissinge$B$N$[$&$r;H$&$he(B  
> e$B$&$K$J$k$O$:$G$9!#e(B

mingw e$B$G$Oe(B configure e$B$G@8@.$5$l$?e(Bconfig.h  
e$B$r;H$&$h$&$G$9$7e(B  
bcc e$B$G$Oe(B msvcrt  
e$B$r;H$o$J$$$h$&$J$N$G!“$=$l$O:G8e$N\<jCJ$K$7$?$$$H;W$$$^$9!#e(B  
e$B$G$9$,%”%I%P%$%9$N$\*$+$2$G$&$^$/$$$+$J$$860x$,$o$+$j$^$7$?!#$"$j$,$H$&$4$6$$$^$9!#e(B  
vsnprinte$B#fe(B e$B$re(B rb\_win32\_vsnprintf  
e$B$G\>e=q$-$7$J$1$l$P$$$$$@$1$@$C$?$h$&$G$9!#e(B

> e$B$A$J$\_$K!"e(Bmissing/vsnprintf.ce$B$X$N=$@5$O$I$&$$$&$b$N$G$7$g$&$+!#e(B

e$B@bL@ITB-$G$7$?!#$9$\_$^$;$s!#e(B  
test\_sprintf\_comb.rb  
e$B$,DL$k$h$&$K=$@5$7$^$7$?!#6qBNE\*$K$O0J2\<$NDL$j$G$9!#e(B

(1) sprintf(“%e”, -1.0000000000000000159e+100)  
e$B!!e(B-\>e$B=$@5A0!'e(B"-1e+100"e$B!!=$@58e!'e(B"-1.000000e+100"  
(2) sprintf(“%.0f”, 0.010000000000000000208)  
e$B!!e(B-\>e$B=$@5A0!'e(B"0.“e$B!!=$@58e!'e(B"0”  
(3) sprintf(“% #±0.f”, -0)  
e$B!!e(B-\>e$B=$@5A0!'e(B"-0"e$B!!=$@58e!'e(B"-0."  
(4) sprintf(“%.0G”, 1)  
e$B!!e(B-\>e$B=$@5A0!'e(B"1E+00"e$B!!=$@58e!'e(B"1"

e$B$G$9$,:#8+D\>$7$F$\_$k$H!"e(B(1)e$B$N=$@5K!$,\>iD9$+$D0UL#ITL@$G$7$?$N$Ge(B  
e$B@h$Ne(B rb\_win32\_vsnprintf e$B$N7o$HJ;$;$F%Q%C%A$r=q$-D\>$7$^$7$?!#e(B

# Index: include/ruby/win32.h

— include/ruby/win32.h (revision 19941)  
+++ include/ruby/win32.h (working copy)  
@@ -243,7 +243,11 @@  
extern void rb\_w32\_free\_environ(char \*\*);  
extern int rb\_w32\_map\_errno(DWORD);

# +#if (defined(\_MSC\_VER) && defined(\_DLL)) || defined( **MSVCRT** ) +#undef HAVE\_VSNPRINTF +#else #define vsnprintf(s,n,f,l) rb\_w32\_vsnprintf(s,n,f,l) +#endif #define snprintf rb\_w32\_snprintf extern int rb\_w32\_vsnprintf(char \*, size\_t, const char \*, va\_list); extern int rb\_w32\_snprintf(char \*, size\_t, const char \*, …); Index: sprintf.c

— sprintf.c (revision 19941)  
+++ sprintf.c (working copy)  
@@ -1018,7 +1018,7 @@  
need += 20;

```
 CHECK(need);

```

- sprintf(&buf[blen], fbuf, fval);

- snprintf(&buf[blen], need, fbuf, fval);  
blen += strlen(&buf[blen]);  
}  
break;  
Index: numeric.c  
===================================================================  
— numeric.c (revision 19941)  
+++ numeric.c (working copy)  
@@ -530,12 +530,12 @@  
else if(isnan(value))  
return rb\_usascii\_str\_new2(“NaN”);

- sprintf(buf, “%#.15g”, value); /\* ensure to print decimal point \*/

- snprintf(buf, 32, “%#.15g”, value); /\* ensure to print decimal  
point _/  
if (!(e = strchr(buf, ‘e’))) {  
e = buf + strlen(buf);  
}  
if (!ISDIGIT(e[-1])) { /_ reformat if ended with decimal point  
(ex 111111111111111.) \*/

- sprintf(buf, “%#.14e”, value);

- snprintf(buf, 32, “%#.14e”, value);  
if (!(e = strchr(buf, ‘e’))) {  
e = buf + strlen(buf);  
}  
@@ -1548,7 +1548,7 @@  
char buf[24];  
char \*s;

- 

```
 sprintf(buf, "%-.10g", RFLOAT_VALUE(val));

```

- 

```
 snprintf(buf, 24, "%-.10g", RFLOAT_VALUE(val));
 if ((s = strchr(buf, ' ')) != 0) *s = '\0';
 rb_raise(rb_eRangeError, "float %s out of range of integer", 

```

buf);  
}  
@@ -1694,7 +1694,7 @@  
char buf[24];  
char \*s;

- 

```
 sprintf(buf, "%-.10g", RFLOAT_VALUE(val));

```

- 

```
 snprintf(buf, 24, "%-.10g", RFLOAT_VALUE(val));
 if ((s = strchr(buf, ' ')) != 0) *s = '\0';
 rb_raise(rb_eRangeError, "float %s out of range of long long", 

```

# buf); } Index: missing/vsnprintf.c

— missing/vsnprintf.c (revision 19941)  
+++ missing/vsnprintf.c (working copy)  
@@ -753,6 +753,8 @@  
#ifdef FLOATING\_POINT  
case ‘e’: /\* anomalous precision \*/  
case ‘E’:

- 

```
 if (prec != 0)

```

- 

```
   flags |= ALT;
 prec = (prec == -1) ?
   DEFPREC + 1 : prec + 1;
 /* FALLTHROUGH */

```

@@ -782,7 +784,7 @@  
cp = cvt(\_double, prec, flags, &softsign,  
&expt, ch, &ndig);  
if (ch == ‘g’ || ch == ‘G’) {

- 

```
   if (expt <= -4 || expt > prec)

```

- 

```
   if (expt <= -4 || (expt > prec && expt > 1))
     ch = (ch == 'g') ? 'e' : 'E';
   else
     ch = 'g';

```

@@ -798,6 +800,8 @@  
size = expt;  
if (prec || flags & ALT)  
size += prec + 1;

- 

```
   } else if (!prec) { /* "0" */

```

- 

```
     size = 1;
   } else /* "0.X" */
     size = prec + 2;
 } else if (expt >= ndig) { /* fixed g fmt */

```

@@ -1008,13 +1012,15 @@  
if (ch \>= ‘f’) { /\* ‘f’ or ‘g’ _/  
if (\_double == 0) {  
/_ kludge for \_\_dtoa irregularity \*/

- 

```
     if (prec == 0 ||

```

- 

```
     if (ndig <= 1 &&
         (flags & ALT) == 0) {
       PRINT("0", 1);
     } else {
       PRINT("0.", 2);
       PAD(ndig - 1, zeroes);
     }

```

- 

```
   } else if (expt == 0 && ndig == 0 && (flags & ALT) == 0) {

```

- 

```
     PRINT("0", 1);
   } else if (expt <= 0) {
     PRINT("0.", 2);
     PAD(-expt, zeroes);

```
