C언어 > printf format string - 위키 백과

TODAY1,507 TOTAL2,701,412
사이트 이용안내
Login▼/회원가입
최신글보기 질문게시판 기술자료 동영상강좌

아두이노 센서 ATMEGA128 PWM LED 초음파 AVR 블루투스 LCD UART 모터 적외선


BASIC4MCU | C언어 | C언어 | printf format string - 위키 백과

페이지 정보

작성자 master 작성일2018-08-24 16:34 조회2,702회 댓글0건

본문

 

printf format string

From Wikipedia, the free encyclopedia
Jump to navigationJump to search

 

An example of the printf function.

printf format string refers to a control parameter used by a class of functions in the input/output libraries of C and many other programming languages. The string is written in a simple template language: characters are usually copied literally into the function's output, but format specifiers, which start with a % character, indicate the location and method to translate a piece of data (such as a number) to characters.

"printf" is the name of the most-used C output function, and stands for "print formatted". printf format strings are complementary to scanf format strings, which provide formatted input (parsing). In both cases these provide simple functionality and fixed format compared to more sophisticated and flexible template engines or parsers, but are sufficient for many purposes.

Many languages other than C copy the printf format string syntax closely or exactly in their own I/O functions.

Mismatches between the format specifiers and type of the data can cause crashes and other vulnerabilities. The format string itself is very often a string literal, which allows static analysis of the function call. However, it can also be the value of a variable, which allows for dynamic formatting but also a security vulnerability known as an uncontrolled format string exploit.

History[edit]

Early programming languages such as Fortran used special statements with completely different syntax from other calculations to build formatting descriptions:

      WRITE OUTPUT TAPE 6, 601, IA, IB, IC, AREA
 601  FORMAT (4H A= ,I5,5H  B= ,I5,5H  C= ,I5,8H  AREA= ,F10.2, 13H SQUARE UNITS)

ALGOL 68 had more function-like api, but still used special syntax (the $ delimiters surround special formatting syntax):

printf(($"Color "g", number1 "6d,", number2 "4zd,", hex "16r2d,", float "-d.2d,", unsigned value"-3d"."l$,
         "red", 123456, 89, BIN 255, 3.14, 250));

But using the normal function calls and data types simplifies the language and compiler, and allows the implementation of the input/output to be written in the same language. These advantages outweigh the disadvantages (such as a complete lack of type safety in many instances) and in most newer languages I/O is not part of the syntax.

C's printf has its origins in BCPL's writef function (1966). *N is a newline, and the order of field width and type are swapped from printf:[1]

WRITEF("%I2-QUEENS PROBLEM HAS %I5 SOLUTIONS*N", NUMQUEENS, COUNT)

Probably the first copying of the syntax to outside the C language was the Unix printf shell command, which first appeared in Version 4, as part of the porting to C.[2]

Format placeholder specification[edit]

Formatting takes place via placeholders within the format string. For example, if a program wanted to print out a person's age, it could present the output by prefixing it with "Your age is ". To denote that we want the integer for the age to be shown immediately after that message, we may use the format string:

printf("Your age is %d", age);

Syntax[edit]

The syntax for a format placeholder is

%[parameter][flags][width][.precision][length]type

Parameter field[edit]

This is a POSIX extension and not in C99. The Parameter field can be omitted or can be:

CharacterDescription
n$n is the number of the parameter to display using this format specifier, allowing the parameters provided to be output multiple times, using varying format specifiers or in different orders. If any single placeholder specifies a parameter, all the rest of the placeholders MUST also specify a parameter.
For example, printf("%2$d %2$#x; %1$d %1$#x",16,17) produces 17 0x11; 16 0x10.

Flags field[edit]

The Flags field can be zero or more (in any order) of:

CharacterDescription
-
(minus)
Left-align the output of this placeholder. (The default is to right-align the output.)
+
(plus)
Prepends a plus for positive signed-numeric types. positive = +, negative = -.
(The default doesn't prepend anything in front of positive numbers.)
 
(space)
Prepends a space for positive signed-numeric types. positive =  , negative = -. This flag is ignored if the + flag exists.
(The default doesn't prepend anything in front of positive numbers.)
0
(zero)
When the 'width' option is specified, prepends zeros for numeric types. (The default prepends spaces.)
For example, printf("%2X",3) produces  3, while printf("%02X",3) produces in 03.
#
(hash)
Alternate form:
For g and G types, trailing zeros are not removed.
For fFeEgG types, the output always contains a decimal point.
For oxX types, the text 00x0X, respectively, is prepended to non-zero numbers.

Width field[edit]

The Width field specifies a minimum number of characters to output, and is typically used to pad fixed-width fields in tabulated output, where the fields would otherwise be smaller, although it does not cause truncation of oversized fields.

The width field may be omitted, or a numeric integer value, or a dynamic value when passed as another argument when indicated by an asterisk *. For example, printf("%*d", 5, 10) will result in    10 being printed, with a total width of 5 characters.

Though not part of the width field, a leading zero is interpreted as the zero-padding flag mentioned above, and a negative value is treated as the positive value in conjunction with the left-alignment - flag also mentioned above.

Precision field[edit]

The Precision field usually specifies a maximum limit on the output, depending on the particular formatting type. For floating point numeric types, it specifies the number of digits to the right of the decimal point that the output should be rounded. For the string type, it limits the number of characters that should be output, after which the string is truncated.

The precision field may be omitted, or a numeric integer value, or a dynamic value when passed as another argument when indicated by an asterisk *. For example, printf("%.*s", 3, "abcdef") will result in abc being printed.

Length field[edit]

The Length field can be omitted or be any of:

CharacterDescription
hhFor integer types, causes printf to expect an int-sized integer argument which was promoted from a char.
hFor integer types, causes printf to expect an int-sized integer argument which was promoted from a short.
lFor integer types, causes printf to expect a long-sized integer argument.

For floating point types, this has no effect.[3]

llFor integer types, causes printf to expect a long long-sized integer argument.
LFor floating point types, causes printf to expect a long double argument.
zFor integer types, causes printf to expect a size_t-sized integer argument.
jFor integer types, causes printf to expect a intmax_t-sized integer argument.
tFor integer types, causes printf to expect a ptrdiff_t-sized integer argument.

Additionally, several platform-specific length options came to exist prior to widespread use of the ISO C99 extensions:

CharactersDescription
IFor signed integer types, causes printf to expect ptrdiff_t-sized integer argument; for unsigned integer types, causes printf to expect size_t-sized integer argument. Commonly found in Win32/Win64 platforms.
I32For integer types, causes printf to expect a 32-bit (double word) integer argument. Commonly found in Win32/Win64 platforms.
I64For integer types, causes printf to expect a 64-bit (quad word) integer argument. Commonly found in Win32/Win64 platforms.
qFor integer types, causes printf to expect a 64-bit (quad word) integer argument. Commonly found in BSD platforms.

ISO C99 includes the inttypes.h header file that includes a number of macros for use in platform-independent printf coding. These need to not be inside double-quotes, e.g. printf("%" PRId64 "\n", t);

Example macros include:

MacroDescription
PRId32Typically equivalent to I32d (Win32/Win64) or d
PRId64Typically equivalent to I64d (Win32/Win64), lld (32-bit platforms) or ld (64-bit platforms)
PRIi32Typically equivalent to I32i (Win32/Win64) or i
PRIi64Typically equivalent to I64i (Win32/Win64), lli (32-bit platforms) or li (64-bit platforms)
PRIu32Typically equivalent to I32u (Win32/Win64) or u
PRIu64Typically equivalent to I64u (Win32/Win64), llu (32-bit platforms) or lu (64-bit platforms)
PRIx32Typically equivalent to I32x (Win32/Win64) or x
PRIx64Typically equivalent to I64x (Win32/Win64), llx (32-bit platforms) or lx (64-bit platforms)

Type field[edit]

The Type field can be any of:

CharacterDescription
%Prints a literal % character (this type doesn't accept any flags, width, precision, length fields).
diint as a signed decimal number. %d and %i are synonymous for output, but are different when used with scanf() for input (where using %i will interpret a number as hexadecimal if it's preceded by 0x, and octal if it's preceded by 0.)
uPrint decimal unsigned int.
fFdouble in normal (fixed-point) notation. f and F only differs in how the strings for an infinite number or NaN are printed (infinfinity and nan for fINFINFINITY and NAN for F).
eEdouble value in standard form ([-]d.ddd e[+/-]ddd). An E conversion uses the letter E (rather than e) to introduce the exponent. The exponent always contains at least two digits; if the value is zero, the exponent is 00. In Windows, the exponent contains three digits by default, e.g. 1.5e002, but this can be altered by Microsoft-specific _set_output_formatfunction.
gGdouble in either normal or exponential notation, whichever is more appropriate for its magnitude. g uses lower-case letters, G uses upper-case letters. This type differs slightly from fixed-point notation in that insignificant zeroes to the right of the decimal point are not included. Also, the decimal point is not included on whole numbers.
xXunsigned int as a hexadecimal number. x uses lower-case letters and X uses upper-case.
ounsigned int in octal.
snull-terminated string.
cchar (character).
pvoid * (pointer to void) in an implementation-defined format.
aAdouble in hexadecimal notation, starting with 0x or 0Xa uses lower-case letters, A uses upper-case letters.[4][5](C++11 iostreams have a hexfloat that works the same).
nPrint nothing, but writes the number of characters successfully written so far into an integer pointer parameter.
Java: indicates a platform neutral newline/carriage return.[6]
Note: This can be utilized in Uncontrolled format string exploits.

Custom format placeholders[edit]

There are a few implementations of printf-like functions that allow extensions to the escape-character-based mini-language, thus allowing the programmer to have a specific formatting function for non-builtin types. One of the most well-known is the (now deprecated) glibc's register_printf_function(). However, it is rarely used due to the fact that it conflicts with static format string checking. Another is Vstr custom formatters, which allows adding multi-character format names.

Some applications (like the Apache HTTP Server) include their own printf-like function, and embed extensions into it. However these all tend to have the same problems that register_printf_function() has.

The Linux kernel printk function supports a number of ways to display kernel structures using the generic %p specification, by appendingadditional format characters.[7] For example, %pI4 prints an IPv4 address in dotted-decimal form. This allows static format string checking (of the %p portion) at the expense of full compatibility with normal printf.

Most non-C languages that have a printf-like function work around the lack of this feature by just using the %s format and converting the object to a string representation. C++ offers a notable exception, in that it has a printf function inherited from its C history, but also has a completely different mechanism that is preferred.

Vulnerabilities[edit]

Invalid conversion specifications[edit]

If the syntax of a conversion specification is invalid, behavior is undefined, and can cause program termination. If there are too few function arguments provided to supply values for all the conversion specifications in the template string, or if the arguments are not of the correct types, the results are also undefined. Excess arguments are ignored. In a number of cases, the undefined behavior has led to "Format string attack" security vulnerabilities.

Some compilers, like the GNU Compiler Collection, will statically check the format strings of printf-like functions and warn about problems (when using the flags -Wall or -Wformat). GCC will also warn about user-defined printf-style functions if the non-standard "format" __attribute__ is applied to the function.

Field width versus explicit delimiters in tabular output[edit]

Using only field widths to provide for tabulation, as with a format like %8d%8d%8d for three integers in three 8-character columns, will not guarantee that field separation will be retained if large numbers occur in the data. Loss of field separation can easily lead to corrupt output. In systems which encourage the use of programs as building blocks in scripts, such corrupt data can often be forwarded into and corrupt further processing, regardless of whether the original programmer expected the output would only be read by human eyes. Such problems can be eliminated by including explicit delimiters, even spaces, in all tabular output formats. Simply changing the dangerous example from before to %7d %7d %7daddresses this, formatting identically until numbers become larger, but then explicitly preventing them from becoming merged on output due to the explicitly included spaces. Similar strategies apply to string data.

Programming languages with printf[edit]

Languages that use format strings that deviate from the style in this article (such as AMPL and Elixir), languages that inherit their implementation from the JVM or other environment (such as Clojure and Scala), and languages that do not have a standard native printf implementation but have external libraries which emulate printf behavior (such as JavaScript) are not included in this list.

See also[edit]

References[edit]

  1. Jump up^ "BCPL"www.cl.cam.ac.uk. Retrieved 19 March 2018.
  2. Jump up^ McIlroy, M. D. (1987). A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986 (PDF) (Technical report). CSTR. Bell Labs. 139.
  3. Jump up^ ISO/IEC (1999). ISO/IEC 9899:1999(E): Programming Languages - C§7.19.6.1 para 7
  4. Jump up^ ""The GNU C Library Reference Manual", "12.12.3 Table of Output Conversions"". Gnu.org. Retrieved 2014-03-17.
  5. Jump up^ "printf" (%a added in C99)
  6. Jump up^ "Formatting Numeric Print Output"The Java Tutorials. Oracle Inc. Retrieved 19 March 2018.
  7. Jump up^ "Linux kernel Documentation/printk-formats.txt". Git.kernel.org. Retrieved 2014-03-17.

External links[edit]

 

 

https://en.wikipedia.org/wiki/Printf_format_string 

 

댓글 0

조회수 2,702

등록된 댓글이 없습니다.

C언어HOME > C언어 > 전체 목록

C언어 목록
제목 작성자 작성일 조회
125 C언어 Timeline of programming languages 이미지 master 18-09-05 3393
현재글 C언어 printf format string - 위키 백과 이미지 master 18-08-24 2703
123 C언어 printf Substitution Types master 18-02-05 2176
122 C언어 Escape sequence master 18-02-05 2187
121 운영체제 없는 프로그래밍 강좌 [펌] qt로 프로그램 만들기 강좌 채팅 서버와 클라이언트 키트 17-09-12 2979
120 운영체제 없는 프로그래밍 강좌 [펌] qt로 프로그램 만들기 강좌 - 서버 키트 17-09-12 2188
119 운영체제 없는 프로그래밍 강좌 [펌] qt로 gui 프로그램 만들기 강좌 - 파일 열기 타이머 키트 17-09-12 2482
118 운영체제 없는 프로그래밍 강좌 [펌] qt로 gui 프로그램 만들기 강좌 - 미로 탈출 키트 17-09-12 2059
117 운영체제 없는 프로그래밍 강좌 [펌] qt로 gui 프로그램 만들기 강좌 - 미로 맵 출력 키트 17-09-12 2491
116 운영체제 없는 프로그래밍 강좌 [펌] qt로 gui 프로그램 만들기 강좌 - 그림띄우기와 충돌처리 키트 17-09-12 2007
115 운영체제 없는 프로그래밍 강좌 [펌] qt로 gui 프로그램 만들기 강좌 - 오늘의 유머 랜덤 베오베 글 키트 17-09-12 2053
114 운영체제 없는 프로그래밍 강좌 [펌] qt로 gui프로그램 만들기 강좌 - 더하기 출력 키트 17-09-12 3600
113 운영체제 없는 프로그래밍 강좌 [펌] 운영체제 없는 프로그래밍 강좌 문자열 출력 키트 17-09-12 1960
112 운영체제 없는 프로그래밍 강좌 [펌] 운영체제 없는 프로그래밍 강좌 문자 1개 출력 키트 17-09-12 1968
111 운영체제 없는 프로그래밍 강좌 [펌] 운영체제 없이 화면에 점찍기 키트 17-09-12 2393
게시물 검색

2022년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2021년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2020년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2019년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2018년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
Privacy Policy
MCU BASIC ⓒ 2020
모바일버전으로보기