Chapter 21: Formatted Input /Output

No Comments

Section 21.1: Conversion Specifiers for printing

Conversion Specifier Type of Argument                                                        Description

Note that length modifiers can be applied to %n (e.g. %hhn indicates that a following n conversion specifier applies to a pointer to a signed char argument, according to the ISO/IEC 9899:2011 §7.21.6.1 ¶7).

Note that the floating point conversions apply to types float and double because of default promotion rules —

§6.5.2.2 Function calls, ¶7 The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.) Thus, functions such as printf() are only ever passed double values, even if the variable referenced is of type float.

With the g and G formats, the choice between e and f (or E and F) notation is documented in the C standard and in the POSIX specification for printf()

The double argument representing a floating-point number shall be converted in the style f or e (or in the style F or E in the case of a G conversion specifier), depending on the value converted and the precision.

Let P equal the precision if non-zero, 6 if the precision is omitted, or 1 if the precision is zero. Then, if a conversion with style E would have an exponent of X:

  • If P > X >= -4, the conversion shall be with style f (or F) and precision P – (X+1).
  • Otherwise, the conversion shall be with style e (or E) and precision P – 1.

Finally, unless the ‘#’ flag is used, any trailing zeros shall be removed from the fractional portion of the result and the decimal-point character shall be removed if there is no fractional portion remaining.

Section 21.2: The printf() Function

Accessed through including <stdio.h>, the function printf() is the primary tool used for printing text to the console in C.

printf(“Hello world!”);

// Hello world!

Normal, unformatted character arrays can be printed by themselves by placing them directly in between the parentheses.

printf(“%d  is  the  answer  to  life,  the  universe,  and  everything.”,  42);

// 42 is the answer to life, the universe, and everything.

int  x  =  3;

char y = ‘Z’;

char* z  =  “Example”;

printf(“Int:  %d,  Char:  %c,  String:  %s”,  x,  y,  z);

// Int: 3, Char: Z, String: Example

Alternatively, integers, floating-point numbers, characters, and more can be printed using the escape character %, followed by a character or sequence of characters denoting the format, known as the format specifier.

All additional arguments to the function printf() are separated by commas, and these arguments should be in the same order as the format specifiers. Additional arguments are ignored, while incorrectly typed arguments or a lack of arguments will cause errors or undefined behavior. Each argument can be either a literal value or a variable.

After successful execution, the number of characters printed is returned with type int. Otherwise, a failure returns a negative value.

Section 21.3: Printing format flags

The C standard (C11, and C99 too) defines the following flags for printf():

Flag      Conversions                                                                   Meaning

These flags are also supported by Microsoft with the same meanings. The POSIX specification for printf() adds:

Section 21.4: Printing the Value of a Pointer to an Object

To print the value of a pointer to an object (as opposed to a function pointer) use the p conversion specifier. It is defined to print void-pointers only, so to print out the value of a non void-pointer it needs to be explicitly converted (“casted*”) to void*.

#include <stdlib.h> /* for EXIT_SUCCESS */

#include <stdio.h>         /* for printf() */

int main(void)

{

int i;

int  *  p  =  &i;

printf(“The  address  of  i  is  %p.\n“,  (void*)  p); return

 EXIT_SUCCESS;

}

Version ≥ C99

Using <inttypes.h> and uintptr_t

Another way to print pointers in C99 or later uses the uintptr_t type and the macros from <inttypes.h>:

#include <inttypes.h> /* for uintptr_t and PRIXPTR */

#include <stdio.h>                                 /* for printf() */

int main(void)

{

int     i;

int  *p  =  &i;

printf(“The  address  of  i  is  0x%”  PRIXPTR  “.\n“,  (uintptr_t)p);

return  0;

}

In theory, there might not be an integer type that can hold any pointer converted to an integer (so the type uintptr_t might not exist). In practice, it does exist. Pointers to functions need not be convertible to the uintptr_t type — though again they most often are convertible.

If the uintptr_t type exists, so does the intptr_t type. It is not clear why you’d ever want to treat addresses as

signed integers, though.

Version = K&R Version < C89

Pre-Standard History:

Prior to C89 during K&R-C times there was no type void* (nor header <stdlib.h>, nor prototypes, and hence no int main(void) notation), so the pointer was cast to long unsigned int and printed using the lx length modifier/conversion specifier.

The example below is just for informational purpose. Nowadays this is invalid code, which very well might provoke the infamous Undefined Behaviour.

#include <stdio.h> /* optional in pre-standard C – for printf() */

int main()

{

int     i;

int  *p  =  &i;

printf(“The  address  of  i  is  0x%lx.\n“,  (long  unsigned)  p);

return  0;

}

Section 21.5: Printing the Dierence of the Values of two Pointers to an Object

Subtracting the values of two pointers to an object results in a signed integer *1. So it would be printed using at least the d conversion specifier.

To make sure there is a type being wide enough to hold such a “pointer-difference”, since C99 <stddef.h> defines the type ptrdiff_t. To print a ptrdiff_t use the t length modifier.

Version ≥ C99

#include <stdlib.h> /* for EXIT_SUCCESS */

#include <stdio.h> /* for printf() */

#include <stddef.h> /* for ptrdiff_t */

int main(void)

{

int  a[2];

int  *  p1  =  &a[0],  *  p2  =  

&a[1]; ptrdiff_t  pd  =  p2  –  p1;

printf(“p1  =  %p\n“,  (void*)  p1);

printf(“p2  =  %p\n“,  (void*)  p2);

printf(“p2  –  p1  =  %td\n“,  pd);

return  EXIT_SUCCESS;

}

The result might look like this:

p1 = 0x7fff6679f430 p2

= 0x7fff6679f434 p2 –

p1 = 1

Please note that the resulting value of the difference is scaled by the size of the type the pointers subtracted point to, an int here. The size of an int for this example is 4.

*1If the two pointers to be subtracted do not point to the same object the behaviour is undefined.

Section 21.6: Length modifiers

The C99 and C11 standards specify the following length modifiers for printf(); their meanings are:

If a length modifier appears with any conversion specifier other than as specified above, the behavior is undefined. Microsoft specifies some different length modifiers, and explicitly does not support hh, j, z, or t.

Note that the C, S, and Z conversion specifiers and the I, I32, I64, and w length modifiers are Microsoft extensions. Treating l as a modifier for long double rather than double is different from the standard, though you’ll be hard- pressed to spot the difference unless long double has a different representation from double.

About us and this blog

We are a digital marketing company with a focus on helping our customers achieve great results across several key areas.

Request a free quote

We offer professional SEO services that help websites increase their organic search score drastically in order to compete for the highest rankings even when it comes to highly competitive keywords.

Subscribe to our newsletter!

More from our blog

See all posts
No Comments

Recent Posts