Problems encountered
I encountered a very strange problem today. After malloc
allocating a heap space, I tried to use cout
and printf
print 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 printf
incomplete display.
Later I figured out that this was caused by the difference between placeholders in C/C++.
C/C++ placeholders %x and %p
%x
Or%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, cout
the pp output by the stream above represents the actual address value, and %p
they have the same meaning. When we use %p
the output, the result is normal:
printf("%p\t%d\n", pp, *pp);
So %x
why is it wrong when outputting? This is because %x
it is int
represented 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, %p
the occupancy becomes 8 bytes, but %x
it is still 4 bytes, so the high bits are truncated.
If correct output is required, we can specify it %llx
so that the output results are consistent:
C/C++ placeholder summary
Format placeholder, the syntax is:
%[*parameter*][*flags*][*field width*][.*precision*][*length*]*type*
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 X are respectively output before non-zero values to represent the number system.0 0x 0X |
0 |
If the width option is prefixed with 0 , padding is used on the left 0 until the width requirement is reached. For example, printf("%2d", 3) " 3 " is output, while printf("%02d", 3) " " is output 03 . If 0 both - and appear, 0 they 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, printf expects an integer argument of char raised size.int |
h |
For integer types, printf expects an integer argument of short raised size.int |
l |
For integer types, printf expects an long integer argument of size. For floating point types, printf expects an double integer argument of size. For string type s, printf a wchar_t pointer argument is expected. For type character c, printf a wint_t parameter of type is expected. |
ll |
For integer types, printf expects an long long integer argument of size. Microsoft is also available I64 . |
L |
For floating point types, printf expects an long double integer argument of size. |
z |
For integer types, printf expects an size_t integer argument of size. |
j |
For integer types, printf expects an intmax_t integer argument of size. |
t |
For integer types, printf expects an ptrdiff_t integer 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. %i When the input value has a prefix 0x or 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 |
double Type 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 |
double Value, the output format is decimal ([ - ]d.ddd e [ + / - ]ddd). E The 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 |
double Type 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 wcrtomb function. |
c |
If the l flag is not used, convert the int parameter to unsigned char type output; if the l flag is used, convert the wint_t parameter to wchart_t an 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 |
double The 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 hexfloat hexadecimal 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} d、i | u 、 o 、 x 、 X \mathrm{u、o、x、X} u、o、x、X | f 、 F 、 e 、 E 、 g 、 G \mathrm{f、F、e、E、g、G} f、F、e、E、g、G | 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 |
参考文献
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.