517 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			517 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <html><head>
 | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 | |
| <link href="sqlite.css" rel="stylesheet">
 | |
| <title>SQLite's Built-in printf()</title>
 | |
| <!-- path= -->
 | |
| </head>
 | |
| <body>
 | |
| <div class=nosearch>
 | |
| <a href="index.html">
 | |
| <img class="logo" src="images/sqlite370_banner.gif" alt="SQLite" border="0">
 | |
| </a>
 | |
| <div><!-- IE hack to prevent disappearing logo --></div>
 | |
| <div class="tagline desktoponly">
 | |
| Small. Fast. Reliable.<br>Choose any three.
 | |
| </div>
 | |
| <div class="menu mainmenu">
 | |
| <ul>
 | |
| <li><a href="index.html">Home</a>
 | |
| <li class='mobileonly'><a href="javascript:void(0)" onclick='toggle_div("submenu")'>Menu</a>
 | |
| <li class='wideonly'><a href='about.html'>About</a>
 | |
| <li class='desktoponly'><a href="docs.html">Documentation</a>
 | |
| <li class='desktoponly'><a href="download.html">Download</a>
 | |
| <li class='wideonly'><a href='copyright.html'>License</a>
 | |
| <li class='desktoponly'><a href="support.html">Support</a>
 | |
| <li class='desktoponly'><a href="prosupport.html">Purchase</a>
 | |
| <li class='search' id='search_menubutton'>
 | |
| <a href="javascript:void(0)" onclick='toggle_search()'>Search</a>
 | |
| </ul>
 | |
| </div>
 | |
| <div class="menu submenu" id="submenu">
 | |
| <ul>
 | |
| <li><a href='about.html'>About</a>
 | |
| <li><a href='docs.html'>Documentation</a>
 | |
| <li><a href='download.html'>Download</a>
 | |
| <li><a href='support.html'>Support</a>
 | |
| <li><a href='prosupport.html'>Purchase</a>
 | |
| </ul>
 | |
| </div>
 | |
| <div class="searchmenu" id="searchmenu">
 | |
| <form method="GET" action="search">
 | |
| <select name="s" id="searchtype">
 | |
| <option value="d">Search Documentation</option>
 | |
| <option value="c">Search Changelog</option>
 | |
| </select>
 | |
| <input type="text" name="q" id="searchbox" value="">
 | |
| <input type="submit" value="Go">
 | |
| </form>
 | |
| </div>
 | |
| </div>
 | |
| <script>
 | |
| function toggle_div(nm) {
 | |
| var w = document.getElementById(nm);
 | |
| if( w.style.display=="block" ){
 | |
| w.style.display = "none";
 | |
| }else{
 | |
| w.style.display = "block";
 | |
| }
 | |
| }
 | |
| function toggle_search() {
 | |
| var w = document.getElementById("searchmenu");
 | |
| if( w.style.display=="block" ){
 | |
| w.style.display = "none";
 | |
| } else {
 | |
| w.style.display = "block";
 | |
| setTimeout(function(){
 | |
| document.getElementById("searchbox").focus()
 | |
| }, 30);
 | |
| }
 | |
| }
 | |
| function div_off(nm){document.getElementById(nm).style.display="none";}
 | |
| window.onbeforeunload = function(e){div_off("submenu");}
 | |
| /* Disable the Search feature if we are not operating from CGI, since */
 | |
| /* Search is accomplished using CGI and will not work without it. */
 | |
| if( !location.origin || !location.origin.match || !location.origin.match(/http/) ){
 | |
| document.getElementById("search_menubutton").style.display = "none";
 | |
| }
 | |
| /* Used by the Hide/Show button beside syntax diagrams, to toggle the */
 | |
| function hideorshow(btn,obj){
 | |
| var x = document.getElementById(obj);
 | |
| var b = document.getElementById(btn);
 | |
| if( x.style.display!='none' ){
 | |
| x.style.display = 'none';
 | |
| b.innerHTML='show';
 | |
| }else{
 | |
| x.style.display = '';
 | |
| b.innerHTML='hide';
 | |
| }
 | |
| return false;
 | |
| }
 | |
| </script>
 | |
| </div>
 | |
| <div class=fancy>
 | |
| <div class=nosearch>
 | |
| <div class="fancy_title">
 | |
| SQLite's Built-in printf()
 | |
| </div>
 | |
| <div class="fancy_toc">
 | |
| <a onclick="toggle_toc()">
 | |
| <span class="fancy_toc_mark" id="toc_mk">►</span>
 | |
| Table Of Contents
 | |
| </a>
 | |
| <div id="toc_sub"><div class="fancy-toc1"><a href="#overview">1. Overview</a></div>
 | |
| <div class="fancy-toc2"><a href="#advantages">1.1. Advantages</a></div>
 | |
| <div class="fancy-toc2"><a href="#disadvantages">1.2. Disadvantages</a></div>
 | |
| <div class="fancy-toc1"><a href="#formatting_details">2. Formatting Details</a></div>
 | |
| <div class="fancy-toc2"><a href="#substitution_types">2.1. Substitution Types</a></div>
 | |
| <div class="fancy-toc2"><a href="#the_optional_length_field">2.2. The Optional Length Field</a></div>
 | |
| <div class="fancy-toc2"><a href="#the_optional_width_field">2.3. The Optional Width Field</a></div>
 | |
| <div class="fancy-toc2"><a href="#the_optional_precision_field">2.4. The Optional Precision Field</a></div>
 | |
| <div class="fancy-toc2"><a href="#the_options_flags_field">2.5. The Options Flags Field</a></div>
 | |
| <div class="fancy-toc1"><a href="#implementation_and_history">3. Implementation And History</a></div>
 | |
| </div>
 | |
| </div>
 | |
| <script>
 | |
| function toggle_toc(){
 | |
| var sub = document.getElementById("toc_sub")
 | |
| var mk = document.getElementById("toc_mk")
 | |
| if( sub.style.display!="block" ){
 | |
| sub.style.display = "block";
 | |
| mk.innerHTML = "▼";
 | |
| } else {
 | |
| sub.style.display = "none";
 | |
| mk.innerHTML = "►";
 | |
| }
 | |
| }
 | |
| </script>
 | |
| </div>
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| <h1 id="overview"><span>1. </span>Overview</h1>
 | |
| 
 | |
| <p>SQLite contains its own implementation of the string formatting routine "printf()",
 | |
| accessible via the following interfaces:
 | |
| 
 | |
| </p><ul>
 | |
| <li> <a href="lang_corefunc.html#printf">printf()</a> → an SQL function returning the formatted string
 | |
| </li><li> <a href="c3ref/mprintf.html">sqlite3_mprintf()</a> → Store the formatted string in memory obtained
 | |
|      <a href="c3ref/free.html">sqlite3_malloc64()</a>.
 | |
| </li><li> <a href="c3ref/mprintf.html">sqlite3_snprintf()</a> → Store the formatted string in a static buffer
 | |
| </li><li> <a href="c3ref/str_append.html">sqlite3_str_appendf()</a> → Append formatted text to a dynamic string
 | |
| </li><li> <a href="c3ref/mprintf.html">sqlite3_vmprintf()</a> → Varargs version of sqlite3_mprintf()
 | |
| </li><li> <a href="c3ref/mprintf.html">sqlite3_vsnprintf()</a> → Varargs version of sqlite3_snprintf()
 | |
| </li><li> <a href="c3ref/str_append.html">sqlite3_str_vappendf()</a> → Varargs version of sqlite3_str_appendf()
 | |
| </li></ul>
 | |
| 
 | |
| <p>The same core string formatter is also used internally by SQLite.
 | |
| 
 | |
| </p><h2 id="advantages"><span>1.1. </span>Advantages</h2>
 | |
| 
 | |
| <p>Why does SQLite have its own private built-in printf() implementation?
 | |
| Why not use the printf() implementation from the standard C library?
 | |
| Several reasons:
 | |
| 
 | |
| </p><p>
 | |
| </p><ol>
 | |
| <li><p>
 | |
| By using its own built-in implementation, SQLite guarantees that the
 | |
| output will be the same on all platforms and in all LOCALEs.
 | |
| This is important for consistency and for testing.  It would be problematic
 | |
| if one machine gave and answer of "5.25e+08" and another gave an answer
 | |
| of "5.250e+008".  Both answers are correct, but it is better when SQLite
 | |
| always gives the same answer.
 | |
| 
 | |
| </p></li><li><p>
 | |
| We know of no way to use the standard library printf() C interface to
 | |
| implement the <a href="lang_corefunc.html#printf">printf() SQL function</a> feature of SQLite.  The built-in
 | |
| printf() implementation can be easily adapted to that task, however.
 | |
| 
 | |
| </p></li><li><p>
 | |
| The printf() in SQLite supports new non-standard substitution
 | |
| types (<a href="printf.html#percentq">%q</a>, <a href="printf.html#percentq">%Q</a>, <a href="printf.html#percentw">%w</a>, and <a href="printf.html#percentz">%z</a>) that are useful both internally to SQLite
 | |
| and to applications using SQLite.
 | |
| Standard library printf()s cannot normally be extended in this way.
 | |
| 
 | |
| </p></li><li><p>
 | |
| Via the <a href="c3ref/mprintf.html">sqlite3_mprintf()</a> and <a href="c3ref/mprintf.html">sqlite3_vmprintf()</a> interfaces,
 | |
| the built-in printf() implementation supports the ability to render an
 | |
| arbitrary-length string into a memory buffer obtained from <a href="c3ref/free.html">sqlite3_malloc64()</a>.
 | |
| This is safer and less error prone than trying to precompute an upper size
 | |
| limit on the result string, allocate an appropriately sized buffer, and
 | |
| then calling snprintf().
 | |
| 
 | |
| </p></li><li><p>
 | |
| The SQLite-specific printf() supports a new flag (!) called the
 | |
| "alternate-form-2" flag.  The alternate-form-2 flag changes the processing
 | |
| of floating-point conversions in subtle ways so that the output is always
 | |
| an SQL-compatible text representation of a floating-point number - something
 | |
| that is not possible to achieve with standard-library printf().  For
 | |
| string substitutions, the alternate-form-2 flag causes the width and
 | |
| precision to be measured in characters instead of bytes, which simplifies
 | |
| processing of strings containing multi-byte UTF8 characters.
 | |
| 
 | |
| </p></li><li><p>
 | |
| The built-in SQLite has compile-time options such as
 | |
| SQLITE_PRINTF_PRECISION_LIMIT that provide defense against 
 | |
| denial-of-service attacks for application that expose the
 | |
| printf() functionality to untrusted users.
 | |
| 
 | |
| </p></li><li><p>
 | |
| Using a built-in printf() implementation means that SQLite has one
 | |
| fewer dependency on the host environment, making it more portable.
 | |
| </p></li></ol>
 | |
| 
 | |
| <h2 id="disadvantages"><span>1.2. </span>Disadvantages</h2>
 | |
| 
 | |
| <p>
 | |
| In fairness, having a built-in implementation of printf() also comes with
 | |
| some disadvantages.  To wit:
 | |
| 
 | |
| </p><ol>
 | |
| <li><p>
 | |
| The built-in printf() implementation uses extra code space 
 | |
| (about 7800 bytes on GCC 5.4 with -Os).
 | |
| 
 | |
| </p></li><li><p>
 | |
| The floating-point to text conversion subfunction for the built-in printf()
 | |
| is limited in precision to 16 significant digits or 26 significant digits
 | |
| if the "!" alternate-form-2 flag is used.
 | |
| Every IEEE-754 double can be represented exactly as a decimal floating-point
 | |
| value, but some doubles require more than 16 or 26 significant digits.
 | |
| 
 | |
| </p></li><li><p>
 | |
| The order of the buffer pointer and buffer size parameters in the built-in
 | |
| snprintf() implementation is reversed from the order used in standard-library
 | |
| implementations.
 | |
| 
 | |
| </p></li><li><p>
 | |
| The built-in printf() implementation does not handle posix positional referencing
 | |
| modifiers that allow the order of arguments to printf() to be different from the
 | |
| order of the %-substitutions.  In the built-in printf(), the order of the arguments
 | |
| must exactly match the order of the %-substitutions.
 | |
| </p></li></ol>
 | |
| 
 | |
| <p>
 | |
| In spite of the disadvantages, the developers believe that having a built-in
 | |
| printf() implementation inside of SQLite is a net positive.
 | |
| 
 | |
| </p><h1 id="formatting_details"><span>2. </span>Formatting Details</h1>
 | |
| 
 | |
| <p>The format string for printf() is a template for the generated
 | |
| string.  Substitutions are made whenever a "%" character appears in
 | |
| the format string.  The "%" is followed by one or more additional
 | |
| characters that describe the substitution.  Each substitution has
 | |
| the following format:
 | |
| 
 | |
| </p><blockquote>
 | |
| <b>%</b><i>[flags][width][</i><b>.</b><i>precision][length]type</i>
 | |
| </blockquote>
 | |
| 
 | |
| <p>All substitutions begin with a single "%" and end with a single type character.
 | |
| The other elements of the substitution are optional.
 | |
| 
 | |
| </p><p>To include a single "%" character in the output, put two consecutive
 | |
| "%" characters in the template.
 | |
| 
 | |
| </p><h2 id="substitution_types"><span>2.1. </span>Substitution Types</h2>
 | |
| 
 | |
| <p>The following chart shows the substitution types supported by SQLite:
 | |
| 
 | |
| </p><center>
 | |
| <table border="1" cellpadding="10" width="80%">
 | |
| <tr>
 | |
| <th>Substitution Type</th><th>Meaning
 | |
| </th></tr><tr>
 | |
| <td>%
 | |
| </td><td>Two "%" characters in a row are translated into a single "%" in the output,
 | |
|     without substituting any values.
 | |
| </td></tr><tr>
 | |
| <td>d, i
 | |
| </td><td>The argument is a signed integer which is displayed in decimal.
 | |
| </td></tr><tr>
 | |
| <td>u
 | |
| </td><td>The argument is an unsigned integer which is displayed in decimal.
 | |
| </td></tr><tr>
 | |
| <td>f
 | |
| </td><td>The argument is a double which is displayed in decimal.
 | |
| </td></tr><tr>
 | |
| <td>e, E
 | |
| </td><td>The argument is a double which is displayed in exponential notation.
 | |
|     The exponent character is 'e' or 'E' depending on the type.
 | |
| </td></tr><tr>
 | |
| <td>g, G
 | |
| </td><td>The argument is a double which is displayed in either normal decimal
 | |
|     notation or if the exponent is not close to zero, in exponential
 | |
|     notation.
 | |
| </td></tr><tr>
 | |
| <td>x, X
 | |
| </td><td>The argument is an integer which is displayed in hexadecimal.
 | |
|     Lower-case hexadecimal is used for %x and upper-case is used
 | |
|     for %X
 | |
| </td></tr><tr>
 | |
| <td>o
 | |
| </td><td>The argument is an integer which is displayed in octal.
 | |
| </td></tr><tr>
 | |
| <td>s, z
 | |
| </td><td>
 | |
| <a name="percentz"></a>
 | |
| 
 | |
|     The argument is a zero-terminated string that is displayed.  For
 | |
|     the %z type in C-language interfaces, <a href="c3ref/free.html">sqlite3_free()</a> is invoked
 | |
|     on the string after it has be copied into the output. The %s and %z
 | |
|     substitutions are identical for the SQL printf() function.<br><br>
 | |
|     The %s substitution is universal, but
 | |
|     the %z substitution is an SQLite enhancement, not found in other
 | |
|     printf() implementations.
 | |
| </td></tr><tr>
 | |
| <td>c
 | |
| </td><td>For the C-language interfaces, the argument is an integer which
 | |
|     is interpreted as a character.  For the <a href="lang_corefunc.html#printf">printf() SQL function</a> the
 | |
|     argument is a string from which the first character is extracted and
 | |
|     displayed.
 | |
| </td></tr><tr>
 | |
| <td>p
 | |
| </td><td>The argument is a pointer which is displayed as a hexadecimal address.
 | |
|     Since the SQL language has no concept of a pointer, the %p substitution
 | |
|     for the <a href="lang_corefunc.html#printf">printf() SQL function</a> works like %x.
 | |
| </td></tr><tr>
 | |
| <td>n
 | |
| </td><td>The argument is a pointer to an integer.  Nothing is displayed for
 | |
|     this substitution type.  Instead, the integer to which the argument
 | |
|     points is overwritten with the number of characters in the generated
 | |
|     string that result from all format symbols to the left of the %n.
 | |
| </td></tr><tr>
 | |
| <td>q, Q
 | |
| </td><td><a name="percentq"></a>
 | |
| 
 | |
|     The argument is a zero-terminated string.  The string is printed with
 | |
|     all single quote (') characters doubled so that the string can safely
 | |
|     appear inside an SQL string literal.  The %Q substitution type also
 | |
|     puts single-quotes on both ends of the substituted string.
 | |
|     <br><br>If the argument
 | |
|     to %Q is a null pointer then the output is an unquoted "NULL".  In other
 | |
|     words, a null pointer generates an SQL NULL, and a non-null pointer generates
 | |
|     a valid SQL string literal.  If the argument to %q is a null pointer
 | |
|     then no output is generated.  Thus a null-pointer to %q is the same as
 | |
|     an empty string.
 | |
|     <br><br>For these  substitutions, the precision is the number of bytes or
 | |
|     characters taken from the argument, not the number of bytes or characters that
 | |
|     are written into the output.
 | |
|     <br><br>
 | |
|     The %q and %Q substitutions are SQLite enhancements, not found in
 | |
|     most other printf() implementations.
 | |
| </td></tr><tr>
 | |
| <td>w
 | |
| </td><td><a name="percentw"></a>
 | |
| 
 | |
|     This substitution works like %q except that it doubles all double-quote
 | |
|     characters (") instead of single-quotes, making the result suitable for
 | |
|     using with a double-quoted identifier name in an SQL statement.
 | |
|     <br><br>
 | |
|     The %w substitution is an SQLite enhancements, not found in
 | |
|     most other printf() implementations.
 | |
| </td></tr></table>
 | |
| </center>
 | |
| 
 | |
| <h2 id="the_optional_length_field"><span>2.2. </span>The Optional Length Field</h2>
 | |
| 
 | |
| <p>The length of the argument value can be specified by one or more letters
 | |
| that occur just prior to the substitution type letter.  In SQLite, the
 | |
| length only matter for integer types.  The length is ignored for the
 | |
| <a href="lang_corefunc.html#printf">printf() SQL function</a> which always uses 64-bit values.  The following
 | |
| table shows the length specifiers allowed by SQLite:
 | |
| 
 | |
| </p><center>
 | |
| <table border="1" cellpadding="10" width="80%">
 | |
| <tr>
 | |
| <th>Length Specifier
 | |
| </th><th>Meaning
 | |
| </th></tr><tr>
 | |
| <td><i>(default)</i>
 | |
| </td><td>An "int" or "unsigned int".  32-bits on all modern systems.
 | |
| </td></tr><tr>
 | |
| <td>l
 | |
| </td><td>A "long int" or "long unsigned int".  Also 32-bits on all modern systems.
 | |
| </td></tr><tr>
 | |
| <td>ll
 | |
| </td><td>A "long long int" or "long long unsigned" or an "sqlite3_int64" or
 | |
|     "sqlite3_uint64" value.  These are 64-bit integers on all modern systems.
 | |
| </td></tr></table>
 | |
| </center>
 | |
| 
 | |
| <p>Only the "ll" length modifier ever makes a difference for SQLite.  And
 | |
| it only makes a difference when using the C-language interfaces.
 | |
| 
 | |
| </p><h2 id="the_optional_width_field"><span>2.3. </span>The Optional Width Field</h2>
 | |
| 
 | |
| <p>The width field specifies the minimum width of the substituted value in
 | |
| the output.  If the string or number that is written into the output is shorter
 | |
| than the width, then the value is padded.  Padding is on the left (the
 | |
| value is right-justified) by default.  If the "-" flag is used, then the
 | |
| padding is on the right and the value is left-justified.
 | |
| 
 | |
| </p><p>The width is measured in bytes by default.  However, if the "!" flag is
 | |
| present then the width is in characters.  This only makes a difference for
 | |
| multi-byte utf-8 characters, and those only occur on string substitutions.
 | |
| 
 | |
| </p><p>If the width is a single "*" character instead of a number, then the
 | |
| actual width value is read as an integer from the argument list.  If the
 | |
| value read is negative, then the absolute value is used for the width and
 | |
| the value is left-justified as if the "-" flag were present.
 | |
| 
 | |
| </p><p>If the value being substituted is larger than the width, then full value
 | |
| is added to the output.  In other words, the width is the minimum width of
 | |
| the value as it is rendered in the output.
 | |
| 
 | |
| </p><h2 id="the_optional_precision_field"><span>2.4. </span>The Optional Precision Field</h2>
 | |
| 
 | |
| <p>The precision field, if it is present, must follow the width separated
 | |
| by a single "." character.  If there is no width, then the "." that introduces
 | |
| the precision immediately follows either the flags (if there are any) or
 | |
| the initial "%".
 | |
| 
 | |
| </p><p>For string substitutions (%s, %z, %q, %Q, or %w) the precision is the number
 | |
| of byte or character used from the argument.  The number is bytes by default but
 | |
| is characters if the "!" flag is present.  If there is no precision, then the
 | |
| entire string is substituted.  Examples:  "%.3s" substitutes the first 3 bytes
 | |
| of the argument string.  "%!.3s" substitutes the first three characters of the
 | |
| argument string.
 | |
| 
 | |
| </p><p>For integer substitutions (%d, %i, %x, %X, %o, and %p) the precision specifies
 | |
| minimum number of digits to display.  Leading zeros are added if necessary, to
 | |
| expand the output to the minimum number of digits.
 | |
| 
 | |
| </p><p>For floating-point substitutions (%e, %E, %f, %g, %G) the precision specifies 
 | |
| the number of digits to display to the right of the decimal point.
 | |
| 
 | |
| </p><p>For the character substitution (%c) a precision N greater than 1 causes the
 | |
| character to be repeated N times.  This is a non-standard extension found only
 | |
| in SQLite.
 | |
| 
 | |
| </p><h2 id="the_options_flags_field"><span>2.5. </span>The Options Flags Field</h2>
 | |
| 
 | |
| <p>Flags consist of zero or more characters that immediately follow the
 | |
| "%" that introduces the substitution.  The various flags and their meanings
 | |
| are as follows:
 | |
| 
 | |
| </p><center>
 | |
| <table border="1" cellpadding="10" width="80%">
 | |
| <tr>
 | |
| <th>Flag
 | |
| </th><th>Meaning
 | |
| </th></tr><tr>
 | |
| <td><b>-</b>
 | |
| </td><td>Left-justify the value in the output.  The default is to right-justify.
 | |
| If the width is zero or is otherwise less than the length of the value being
 | |
| substituted, then there is no padding and the "-" flag is a no-op.
 | |
| </td></tr><tr>
 | |
| <td><b>+</b>
 | |
| </td><td>For signed numeric substitutions, include a "+" sign before positive numbers.
 | |
| A "-" sign always appears before negative numbers regardless of flag settings.
 | |
| </td></tr><tr>
 | |
| <td><i>(space)</i>
 | |
| </td><td>For signed numeric substitutions, prepend a single space before positive
 | |
| numbers.
 | |
| </td></tr><tr>
 | |
| <td><b>0</b>
 | |
| </td><td>Prepend as many "0" characters to numeric substitutions as necessary to
 | |
| expand the value out to the specified width.  If the width field is omitted,
 | |
| then this flag is a no-op.
 | |
| </td></tr><tr>
 | |
| <td><b>#</b>
 | |
| </td><td>This is the "alternate-form-1" flag.
 | |
| For %g and %G substitutions, this causes trailing zeros to be removed.
 | |
| This flag forces a decimal point to appear for all floating-point substitutions.
 | |
| For %o, %x, and %X substitutions, the alternate-form-1 flag cause the value
 | |
| to be prepended with "0", "0x", or "0X", respectively.
 | |
| </td></tr><tr>
 | |
| <td><b>,</b>
 | |
| </td><td>This flag causes comma-separators to be added to the output of %d and %i
 | |
| substitutions, between every 3 digits from the left.  This can help humans
 | |
| to more easily discern the magnitude of large integer values.  For example,
 | |
| the value 2147483647 would be rendered as "2147483647" using "%d" but would
 | |
| appear as "2,147,483,647" with "%,d".  This flag is a non-standard extension.
 | |
| </td></tr><tr>
 | |
| <td><b>!</b>
 | |
| </td><td>This is the "alternate-form-2 flag.
 | |
| For string substitutions, this flag causes the width and precision to be understand
 | |
| in terms of characters rather than bytes.
 | |
| For floating point substitutions, the alternate-form-2 flag increases the 
 | |
| maximum number of significant digits displayed from 16 to 26,
 | |
| forces the display of the decimal point and causes at least one digit
 | |
| to appear after the decimal point.<br><br>
 | |
| The alternate-form-2 flag is a non-standard extension that appears in no
 | |
| other printf() implementations, as far as we know.
 | |
| </td></tr></table>
 | |
| </center>
 | |
| 
 | |
| <h1 id="implementation_and_history"><span>3. </span>Implementation And History</h1>
 | |
| 
 | |
| <p>
 | |
| The core string formatting routine is the sqlite3VXPrintf() function found in the
 | |
| <a href="https://sqlite.org/src/file/src/printf.c">printf.c</a> source file.  All the
 | |
| various interfaces invoke (sometimes indirectly) this one core function.
 | |
| The sqlite3VXPrintf() function began as code written by the first author
 | |
| of SQLite (<a href="crew.html">Hipp</a>) when he was a graduate student a Duke University in the
 | |
| late 1980s.  Hipp kept this printf() implementation in his personal toolbox until
 | |
| he started working on SQLite in 2000.  The code was incorporated into the
 | |
| SQLite source tree on <a href="https://sqlite.org/src/timeline?c=f9372072a6">2000-10-08</a>
 | |
| for SQLite version 1.0.9.
 | |
| 
 | |
| </p><p>
 | |
| The <a href="https://www.fossil-scm.org/">Fossil Version Control System</a> uses its own
 | |
| printf() implementation that is derived from an early version of the SQLite
 | |
| printf() implementation, but those two implementations have since diverged.
 | |
| 
 | |
| </p><p>
 | |
| The reason that the <a href="c3ref/mprintf.html">sqlite3_snprintf()</a> has its buffer pointer and buffer size
 | |
| arguments reversed from what is found in the standard library snprintf() routine
 | |
| is because there was no snprintf() routine in the standard C library
 | |
| when Hipp was first implementing his version, and he chose a different order
 | |
| than the designers of the standard C library.
 | |
| </p>
 |