how does printf %n count characters? [duplicate] - c

This question already has answers here:
What is the use of the %n format specifier in C?
(12 answers)
Closed 7 years ago.
#include <stdio.h>
int main()
{
int val;
printf("blah%p%nblah", &val, &val);
printf("val = %d\n", val);
return 0;
}
This demo program is complied on 32-bit machine. I think val should be 8.
But I got this:
$ ./a.out
blah0xffa9b6fcblahval = 14
Why 14? blah is 4 chars. A pointer in IA32 should be 4 bytes. %n prints nothing.

Please count the number of printed characters, they are 14.
The value stored in the variable int pointer the "%n" specifier is the number of characters printed prior to the occurrance of the "%n" specifier, there are 10 for the poitner address and 4 for blah.
blah0xffa9b6fc /* these are exactly 14 characters
^ ^
%s %p
*/

Just to support what Mr. Iharob said in his answer,
Quoting from C11, chapter §7.21.6.1, fprintf(), (emphasis mine)
n
The argument shall be a pointer to signed integer into which is written the
number of characters written to the output stream so far by this call to
fprintf. No argument is converted, but one is consumed. If the conversion
specification includes any flags, a field width, or a precision, the behavior is
undefined.
So, it does not count the bytes in format string, rather, the actual printed bytes.
That said, the recommended signature of main() is int main(void).

This output string (before format specifier %n will be encountered)
blah0xffa9b6fc
contains exactly 14 symbols. The reason for val contains 14 is that format specifier %p outputs addresses in the hexadecimal notation
0xffa9b6fc
And indeed in your platform pointers have size of 4 bytes.:)

Related

what is the “%1$d” output meaning? [duplicate]

This question already has answers here:
How do positional arguments like "1$" work with printf()?
(4 answers)
Closed 3 years ago.
im using ubuntu to run this code. but what does the code mean?
running ubuntu code:
gcc name.c -o name
/name
#include <stdio.h>
int main(void)
{
printf("%d %1$d %2$d",5);
}
the output is "5 5 random number ". So, what meaning of %2$d?
The 1$ and 2$ specifies the position of the argument. It's only specified by POSIX, it is not in C standard.
According to the C standard the behavior of printf here is undefined anyway, as the $ is not a valid printf conversion specification.
According to fprintf posix:
[...] In format strings containing the "%n$" form of a conversion
specification, a field width or precision may be indicated by the
sequence "*m$", where m is a decimal integer in the range
[1,{NL_ARGMAX}] giving the position in the argument list (after the
format argument) of an integer argument containing the field width or
precision, for example:
printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);
So:
printf("%d %1$d %2$d",5);
%d - specifies that the next int argument should be converted to a signed decimal.
%1$d - specifies that the first after format string int argument should be converted to a signed decimal
%2$d - specifies that the second after format string int argument should be converted to a signed decimal
You gave only two arguments to the printf function (the format string and 5). The result is undefined, because 2$ expects another argument.

Im confused regarding %p specifier [duplicate]

This question already has answers here:
Difference between %d and %p printf format string directives in c language?
(3 answers)
Closed 5 years ago.
#include <stdio.h>
int main(void)
{
int i=10;
printf("%p",i);
return 0;
}
output:-
0xa
%p - I have read %p is used to print pointer in printf, but here i is an integer,and also there is no pointer declared so how "0xa" gets output.
The behaviour of your code is undefined since an %p is not an appropriate format specifier for an int type.
The compiler is allowed to do anything, which includes optimising your code to int main(){}.
Technically it is undefined behaviour because %p is the wrong format specifier for an int.
But if your platform is 32 bits, then %p usually boils down to printing the supplied value in hexadecimal on most implementations and therefore printf("%p", 10); will usually print 0xA or 0x0000000A on these implementations.
Anyway, don't use unmatched format specifiers, because even if it appears to work, it results in undefined behaviour.

What exactly is %p and why is it different from printing the int value of pointer by using %d? [duplicate]

This question already has answers here:
What happens when I use the wrong format specifier?
(2 answers)
Closed 6 years ago.
#include <stdio.h>
int main()
{
int *ptr;
int a=2;
ptr=&a;
printf("%p\n",ptr);
printf("%d\n",ptr);
printf("%p\n",a);
return 0;
}
The output I get is:
% ./a.out
0x7ffe12032c40
302197824
0x2
%
The value of the first two output changes (obviously because of ASLR) and the 0x2 remains constant.
The size of pointer isn't equal size of int, So you can't use %d instead of %p, %p is used for printing value stored in pointer variable, also using %p with int variable is undefined behavior (if you're on system which pointer and int have same size you may see correct result, but as C standard its an undefined behavior )
sizeof int is defined by compiler, different compilers may have different size of int on single machine, but pointer size is defined by machine type (8,16,32,64 bit)
0x2 is simply the hex representation of integer 2.
That is why you see that output
printf() prints the value of variable a in hex format. If you want to print the address of a, do the following
printf("%p",&a);
When you use %p as in
printf("%p\n",ptr);
%p is the format specifier for pointers, you get the expected results
When you use %d as in
printf("%d\n",ptr);
%d is the format specifier for signed integers, you get unexpected results because the size of pointers (which is usually 8 bytes) can be different from size of signed integers(which is usually 4 bytes).
It is for printing pointers. In the same way you don't print a float with %d you should not be printing a pointer with %d.

understanding weird output of printf function

According to me
int a=0;
printf("%d",a);
works same as
char *ptr="%d"
ptr points to % and then ptr reads the whole string from % and 4 bytes are read from memory.
Now consider the below code
printf("%d"+1,a); //value of a=0
is same as
char *ptr="%d"
ptr+=1;
ptr now points to d and so string from d is printed
Now
printf(1+"Alex"); //prints lex
ptr points l and prints string from there on....
Now what will happen in the following cases?It appears to be out of my scope.
printf("%",a);
printf("%%%%");
printf("%%d",a);
printf("%",a); does not have a valid conversion specifier, so it is covered by:
§7.21.6.1
9 If a conversion specification is invalid, the behavior is
undefined. If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.
printf("%%%%"); will simply print %%, since %% is a conversion specifier. See the printf man pages.
%
A '%' is written. No argument is converted. The complete conversion
specification is '%%'.
As mentioned in the comments, printf("%%d",a); is probably not undefined behavior. %% becomes % and the a is ignored.
§7.21.6.1
2 The fprintf function writes output to the stream pointed to by stream,
under control of the string pointed to by format that specifies how
subsequent arguments are converted for output. If there are
insufficient arguments for the format, the behavior is undefined. If
the format is exhausted while arguments remain, the excess arguments
are evaluated (as always) but are otherwise ignored. The fprintf
function returns when the end of the format string is encountered.
I hope that this quote from the C Standard will help you
8 The conversion specifiers and their meanings are:
% A % character is written. No argument is converted. The complete
conversion specification shall be %%.
For example
printf("%%%%");
will output
%%

How integers numbers are printed with %f specifier? [duplicate]

This question already has answers here:
Unexpected output of printf
(4 answers)
Closed 9 years ago.
#include<stdio.h>
main()
{
int a = 66;
printf("%f", a);
}
It is printing 0.0000 as an answer, why?
And %f is replaced with %c it is printing B. I am not getting the reason.
Please explain !!
It is because your program invokes undefined behavior. You may get anything, either expected or unexpected.
C11: 7.29.2 Formatted wide character input/output functions:
If a conversion specification is invalid, the behavior is undefined.335) If any argument is not the correct type for the corresponding conversion specification, the behavior is
undefined.
printf("%f",a);
^ %f specifier expects arguments of type float/ double.
And %f is replaced with %c it is printing B. I am not getting the reason
ASCII code of character B is 66. Using %c specifier prints the (printable) character itself.
For printf():
[...] If any argument is not the type expected by the corresponding conversion specifier, or if there are less arguments than required by format, the behavior is undefined. If there are more arguments than required by format, the extraneous arguments are evaluated and ignored [...]
Although, for %c, you correctly get the expected 'B' (whose ASCII code is 66), it is not recommended (imaging when you pass in 666, which will get unexpected result as no ASCII code is 666). At least, you should do type-casting beforehand:
printf("%f", (float)a);
printf("%c", (char)a);
Again, remember always use the corresponding specifiers for different types.
If you use %f specifier and do not provide a float number, but int, the behaviour is undefined. In practice the memory starting in the location where your int is will be interpreted as float number, so what gets printed depends on internal representation of ints and floats.
For %c you got B since %c interprets your int as character code, and B's code is 66.
%f is used to print floating point number
%c is used to print character
%d is used to print integer number
so when you are using %c printf function converting from ascii value to character of B.
if you want to print the integer
printf("%d",a);
%c prints the character corresponding to 66 into ascii table.
By default %f will print 5 digits after the decimal point, but you can change the behaviour with %.3f (for 3 digits)

Resources