C language printf function of the use of details

  • 2020-04-01 23:31:23
  • OfStack

The full format of printf's format control:
% - 0 m n l or h format character
The items that comprise the format description are described below:
% : the beginning symbol of the format description, indispensable.
- : there is - to indicate left - aligned output, such as omitted means right - aligned output.
0:0 indicates that the specified space is filled with 0, if the omission indicates that the specified space is not filled.
M.n: m refers to the width of the field, that is, the number of characters occupied by the corresponding output item on the output device. N is for precision. The number of decimal places used to describe the output real number. When n is specified, the implied precision is n=6 bits.
L or h:l pair of integer refers to the long type, pair of real refers to the double type. H is used to modify the format character of an integer to short.

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Format characters
Format characters are used to specify the data type and output format of the output item.

D format: used to output decimal integer. It can be used in the following ways:
%d: output by the actual length of the integer data.
%md: m is the width of the specified output field. If the number of digits of the data is less than m, the left end is filled with space; if the number is greater than m, the output is as the actual number.
%ld: outputs long integer data.
O format: output integers in unsigned octal form. Long integers can be output in the "%lo" format. You can also specify the field width for output in the format "%mo".
Ex. :


main()
{ 
   int a = -1;
   printf("%d, %o", a, a);
}

Running result: -1,177777
Program analysis: -1 in the CD (in the form of a complement) is (111111111111111111)2, converted to the octal number (177777)8.
X format: output integers in unsigned hexadecimal form. Long integers can be output in "%lx" format. You can also specify the field width and output it in "%mx" format.
U format: output integers in unsigned decimal form. Long integers can be output in "%lu" format. You can also specify the field width to be output in the format "%mu".
(c format: output one character.
S format: used to output a string. There are several USES
%s: for example :printf("%s", "CHINA") prints the "CHINA" string (excluding double quotes).
%ms: the output string occupies m column, if the length of the string itself is greater than m, the limit of m will be broken, the string is all output. Left padding if the string length is less than m.
%-ms: if the string length is less than m, then in the m column range, the string is to the left, right padding space.
%m.ns: the output takes m column, but only takes n characters from the left end of the string. The n characters are printed on the right side of the m column, left padding.
%-m.ns: where m and n have the same meaning as above, and n characters are output in the left side of the m column range, right padding space. If n > M, automatically take the value of n, that is, to ensure the normal output of n characters.
F format: used to output real Numbers (including single, double precision), in the form of decimal output. It can be used in the following ways:
%f: no width is specified, the integer part is output in its entirety and 6 decimal places are output.
%m.nf: the output takes up m column, in which there are n decimal places, such as the value width is less than m left supplementary space.
%-m.nf: the output occupies n columns, in which there are n decimal places, such as the value width is less than m right end of the space.
Format e: output real Numbers in an exponential form. The following forms can be used:
%e: the numeric part (also called mantisse) outputs 6 decimal places, and the exponent part has 5 or 4 places.
The characters m, n and "-" have the same meaning as before. Where n is the number of decimal places in the numeric part of the data, and m is the width occupied by the entire output data.
9 g format: automatically selects the shorter output in f or e format, and does not output meaningless zeros.

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Further description of printf function:
If you want to output the character "%", you should use two consecutive % in the format control string, such as:
Printf (" % % % f ", 1.0/3);
The output of 0.333333%.

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
For single-precision Numbers, when the %f format character is used, only the first 7 digits are significant digits and the decimal number is 6 digits.
For doubles, the %lf format is used to output the first 16 digits as significant digits and the decimal 6 digits.

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # gleanings # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Guided by a master
The format of m.n can also be expressed in the following way (example)
Char ch [20].
Printf (" % *. * s \ n ", m, n, ch);
The * in the front defines the total width, and the * in the back defines the number of outputs. That corresponds to the outer parameters m and n. I think the advantage of this approach is that you can assign values to m and n outside of the statement to control the output format.

%n can assign the length value of the output string to a variable, as shown in the following example:

Int slen;

Printf (" hello world % n, & slen);

After execution, the variable is assigned a value of 11.

Looking up again, I saw an article (see) that said the output in this format had been identified as a security concern and had been disabled. Search again sure enough this usage is used to make what overflow, vulnerability and so on, just found a: format string attack notes.

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

The %p format is used to output memory addresses as hexadecimal integers


#include <stdio.h>
extern int etext, edata, end;
int main(void)
{
   printf("etext: t%pn", &etext);
   printf("edata: t%pn", &edata);
   printf("end: t%pn", &end);
   return(0);
}

During the linking process, the linkers ld and ld86 use variables to record the logical address of each segment in the executing program. Therefore, you can access these external variables to obtain the position in the middle of the program. The external variables predefined by the linker are usually at least etext, _etext, edata, _edata, end, and _end.

The variable name _etext and the address of etext are the first address after the end of the body of the program. The address of _edata and edata is the first address after the initialization data area. The addresses of _end and end are the first address location after the uninitialized data area (BSS). Names with the underscore '_' prefix are equivalent to their ununderlined counterparts, the only difference being that the ANSI, POSIX, and other standards do not define the symbols etext, edata, and end.

When the program first executes, its BRK is in the same position as _end. But operations such as sys_brk(), the memory allocation function malloc(), and standard input/output change this location. Therefore, the current BRK position of the program needs to be obtained using SBRK (). Note that these variable names must be thought of as addresses. Therefore, when accessing them, you need to use the take address prefix '&', such as &end, etc. Such as:

Extern int _etext;
Int et;

(int *) et = &_etext; // at this point et contains the address after the end of the body paragraph.

The following program, predef.c, can be used to display the addresses of these variables. You can see that the address value with and without the underscore '_' symbol is the same.



extern int end, etext, edata;
extern int _etext, _edata, _end;
int main(void)
{
   printf("&etext=%p, &edata=%p, &end=%pn", &etext, &edata, &end);
   printf("&_etext=%p, &_edata=%p, &_end=%pn", &_etext, &_edata, &_end);
   return 0;
}

Running the program on a Linux 0.1x system yields the following results. Note that these addresses are logical addresses in the program address space, that is, from the time the executing program is loaded into the memory location.

[/usr/root]# gcc-o predef predef.c
The/usr/root #. / predef
& etext = 4000, & edata = 44 c0, & end = 48 d8
& _etext = 4000, & _edata = 44 c0, & _end = 48 d8
The/usr/root #

If you run this program on a current Linux system, such as RedHat 9, you get the following results. We know that the program code in the Linux system now starts at its logical address 0x08048000, so we know that the code segment length of this program is 0x41b bytes.

[root @ plinux] #. / predef
& etext = 0 x804841b, & edata = 0 x80495a8, & end x80495ac = 0
& _etext = 0 x804841b, & _edata = 0 x80495a8, & _end x80495ac = 0
[root @ plinux] #

When the Linux 0.1x kernel initializes the block device buffer (fs/buffer.c), it USES the variable name _end to get the location behind the end of the kernel Image file Image in memory, and from there the buffer is set.

The attached:
C51 printf function
The optional characters l or l may precede The type character to specify long types for d, I, u, o, x, and x.
The optional characters b or b may immediately precede e The type character to specify char types for d, I, u, o, x, and x.
Printf (" % bx, "(char), I);

If it is
Int a; Can be sprintf(buf,"%d",a), the result is correct
Char a must be sprintf(buf,"bd",a)
Sprintf (buf,"%1.3f",a)
What about printf("%02BX%02BX\n", adch, adcl)? It should be the expression on C51


Related articles: