C/C++ placeholder, the difference between %x and %p

Problems encountered

I encountered a very strange problem today. After mallocallocating a heap space, I tried to use coutand printfprint the address respectively. The two addresses were different:

int *pp = (int*)malloc(10*sizeof(int));
*pp = 1234;
cout << pp << '\t' << *pp << endl;
printf("0x%x\t%d\n", pp, *pp);
free(pp);

It can be seen that the lower 32 bits of the two addresses are consistent, and the cause of the problem should be printfincomplete display.

image-20230423162758215

Later I figured out that this was caused by the difference between placeholders in C/C++.

C/C++ placeholders %x and %p

%xOr %X: represents the hexadecimal expression of the input number, the length is 32 bits

%p: Represents the pointer (address) value of the input variable, a hexadecimal number, the length is determined by the current operating system

In fact, coutthe pp output by the stream above represents the actual address value, and %pthey have the same meaning. When we use %pthe output, the result is normal:

printf("%p\t%d\n", pp, *pp);

image-20230423172245192

So %xwhy is it wrong when outputting? This is because %xit is intrepresented by occupying 4 bytes. In 16-bit and 32-bit systems, since the address does not exceed 4 bytes, there will be no difference in the output of %x and %p.

But in a 64-bit system, %pthe occupancy becomes 8 bytes, but %xit is still 4 bytes, so the high bits are truncated.

If correct output is required, we can specify it %llxso that the output results are consistent:

image-20230423173910954

C/C++ placeholder summary

Format placeholder, the syntax is:

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

Printf.svg

Parameter can be ignored or:

character describe
*n*$ n is the number of parameters displayed using this format specifier; this allows the parameters to be output multiple times, using multiple format specifiers, and output in different orders. If any placeholder uses parameter , all other placeholders must also use parameter . This is a POSIX extension and is not part of ISO C. Example: printf("%2$d %2$#x; %1$d %1$#x",16,17)produce " 17 0x11; 16 0x10"

Flags can be 0 or more:

character describe
+ Always represents the ' +' or ' -' sign of a signed value. The default is to ignore the sign of a positive number. Applies to numeric types only.
space Makes the output of signed numbers prefixed by 1 space if there is no sign or 0 characters are output. If whitespace occurs with '+', the whitespace specifier is ignored.
- Align left. The default is right-aligned.
# For ' g' and ' G', trailing zeros are not removed to indicate precision. For ' f', ' F', ' e', ' E', ' g', ' G', the decimal point is always output. For ' o', ' x', ' ', prefixes , , and Xare respectively output before non-zero values ​​to represent the number system.00x0X
0 If the width option is prefixed with 0, padding is used on the left 0until the width requirement is reached. For example, printf("%2d", 3)" 3" is output, while printf("%02d", 3)" " is output 03. If 0both -and appear, 0they are ignored, that is, left-aligned and still padded with spaces.

Field Width gives the minimum width of the displayed value, typically used to fill fixed-width entries in tabular output. If the actual number of output characters is less than the field width, padding will be performed according to left or right alignment. If the actual number of output characters exceeds the field width, it will not cause numerical truncation, but will display all characters. Leading 0s in a width value are interpreted as a 0-padding flag, as above; leading negative values ​​are interpreted as their absolute value , and the negative sign is interpreted as a left-justify flag. If the domain width value is *, then the value of the corresponding function parameter is the current domain width.

Precision usually specifies the maximum length of the output, depending on the specific formatting type. For integer values ​​​​of d, i, u, x, and o, it refers to the minimum number of digits. The insufficient digits must be filled with 0 on the left. If it exceeds, it will not be truncated. The default value is 1. For the floating point values ​​​​of a, A, e, E, f, F, it refers to the number of digits displayed to the right of the decimal point. If necessary, round off or add 0; the default value is 6. For g, the floating point value of G refers to the maximum number of significant digits ; the default value is 6. For the string type of s, it refers to the upper limit of the output bytes. Other characters exceeding the limit will be truncated. If the domain width is *, then the value of the corresponding function parameter is the current domain width. If only the decimal point is given, the field width is 0.

Length indicates the length of the floating point parameter or integer parameter. This item is called "Size" by Microsoft. Can be ignored, or as follows:

character describe
hh For integer types, printfexpects an integer argument of charraised size.int
h For integer types, printfexpects an integer argument of shortraised size.int
l For integer types, printfexpects an longinteger argument of size.
For floating point types, printfexpects an doubleinteger argument of size.
For string type s, printfa wchar_tpointer argument is expected.
For type character c, printfa wint_tparameter of type is expected.
ll For integer types, printfexpects an long longinteger argument of size. Microsoft is also available I64.
L For floating point types, printfexpects an long doubleinteger argument of size.
z For integer types, printfexpects an size_tinteger argument of size.
j For integer types, printfexpects an intmax_tinteger argument of size.
t For integer types, printfexpects an ptrdiff_tinteger argument of size.

Type Type , also called conversion specification/specifier, can be:

character describe
d, i Signed decimal value int. ' %d' and ' %i' are synonymous for output; but scanf()they are different for input. %iWhen the input value has a prefix 0xor 0, it represents a hexadecimal or octal value respectively. If precision is specified, zeros are padded on the left if the output number is insufficient. The default precision is 1. With precision 0 and value 0, the output is empty.
u decimal unsigned int. If precision is specified, zeros are padded on the left if the output number is insufficient. The default precision is 1. With precision 0 and value 0, the output is empty.
f,F doubleType output decimal fixed point representation. The difference between ' f' and ' F' is that when infinity and NaN are expressed, ' f' output ' inf', ' infinity' and ' nan'; ' F' output ' INF', ' INFINITY' and ' NAN'. The number of digits after the decimal point equals the precision, and the last digit is rounded off . Precision defaults to 6. If the precision is 0 and there is no # mark, no decimal point appears. At least one digit to the left of the decimal point.
e, E doubleValue, the output format is decimal ([ -]d.ddd e[ +/ -]ddd). EThe exponent symbol used by the version is E(instead of e). The exponent part contains at least 2 digits, if the value is 0, then the exponent part is 00. For Windows systems, the exponent part must be at least 3 digits. For example 1.5e002, it can also be modified using the Microsoft version of the runtime function _set_output_format. There is 1 digit before the decimal point. The number of digits after the decimal point equals the precision. Precision defaults to 6. If the precision is 0 and there is no # mark, no decimal point appears.
g,G doubleType numeric value, precision is defined as the total number of significant digits. When the exponential part is within the closed interval [-4,5], the output is in fixed-point form; otherwise, the output is in exponential floating-point form. ' g'Use lowercase letters, ' G'Use uppercase letters. The digit 0 to the right of the decimal point is not displayed; the decimal point is displayed only when the decimal part of the output is not 0.
x,X Hexadecimal unsigned int. ' x'Use lowercase letters;' X'Use uppercase letters. If precision is specified, zeros are padded on the left if the output number is insufficient. The default precision is 1. With precision 0 and value 0, the output is empty.
o octal unsigned int. If precision is specified, zeros are padded on the left if the output number is insufficient. The default precision is 1. With precision 0 and value 0, the output is empty.
s If the l flag is not used, a null-terminated string is output up to the upper limit specified by the precision; if no precision is specified, all bytes are output. If the l flag is used, the corresponding function parameter points to an array of wchar_t type, and each wide character is converted into a multi-byte character during output, which is equivalent to calling a wcrtombfunction.
c If the l flag is not used, convert the int parameter to unsigned chartype output; if the l flag is used, convert the wint_t parameter to wchart_tan array containing two elements, where the first element contains the character to be output, and the second element is null wide. character.
p void *mold
a, A doubleThe hexadecimal representation of the type is "[−]0 x h.hhhh p ±d". The exponent part is expressed in decimal notation. For example: 1025.010 output is 0x1.004000p+10. ' a'Use lowercase letters, ' A'Use uppercase letters. [ 2] [ 3] (C++11 stream uses hexfloathexadecimal floating point output)
n No characters are output, but the number of characters that have been successfully output is written to the variable pointed to by the corresponding integer pointer parameter.
% ' %'Literal value, does not accept any flags, width, precision or length.
length <------ -------------------- -------- type -------- ------ ------ ------>
d 、 i \mathrm{d、i} di u 、 o 、 x 、 X \mathrm{u、o、x、X} uoxX f 、 F 、 e 、 E 、 g 、 G \mathrm{f、F、e、E、g、G} fFeEgG c \mathrm{c} c s \mathrm{s} s p \mathrm{p} p
(none) int unsigned int double char char * void *
h h \mathrm{hh} hh signed char unsigned char
h \mathrm{h} h short int unsigned short int
l \mathrm{l} l long int unsigned long int wint_t wchar_t
l l \mathrm{ll} ll long long int unsigned long long int
L \mathrm{L} L long double
j \mathrm{j} j intmax_t uintmax_t
z \mathrm{z} z size_t ssize_t
t \mathrm{t} t ptrdiff_t ptrdiff_t

参考文献

1:C语言中的%p和%x的区别_百度知道

2: Format string - Wikipedia, the free encyclopedia

If you have any questions or errors, please feel free to message me privately for corrections.
All rights reserved. Please do not reproduce without authorization!
Copyright © 2023 by Mr.Idleman. All rights reserved.

Guess you like

Origin blog.csdn.net/qq_42059060/article/details/130328448