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

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.

Related

Why is the result of -5/2 being printed as 0? [duplicate]

This question already has answers here:
What happens when I use the wrong format specifier?
(2 answers)
Closed 1 year ago.
Can you tell why this statement in C gives 0 as output
printf("Hello %f",-5/2);
Whereas
printf("Hello %d",-5/2);
is giving output as -2
Division of two integers produces a integer result (int in this case). The %f format specifier expects an argument of type double. Using the wrong format specifier for a given argument triggers undefined behavior which in this case gives you an incorrect result.
If you want a floating point result, at least one of the operands to / must have a floating point type, i.e.
printf("Hello %f",-5.0/2);

why printf behaves differently when we try to print float as a hexadecimal? [duplicate]

I tried to print character as a float in printf and got output 0. What is the reason for this.
Also:
char c='z';
printf("%f %X",c,c);
is giving some weird output for hexadecimal while output is correct when I do this:
printf("%X",c);
why is it so?
The printf() function is a variadic function, which means that you can pass a variable number of arguments of unspecified types to it. This also means that the compiler doesn't know what type of arguments the function expects, and so it cannot convert the arguments to the correct types. (Modern compilers can warn you if you get the arguments wrong to printf, if you invoke it with enough warning flags.)
For historical reasons, you can not pass an integer argument of smaller rank than int, or a floating type of smaller rank than double to a variadic function. A float will be converted to double and a char will be converted to int (or unsigned int on bizarre implementations) through a process called the default argument promotions.
When printf parses its parameters (arguments are passed to a function, parameters are what the function receives), it retrieves them using whatever method is appropriate for the type specified by the format string. The "%f" specifier expects a double. The "%X" specifier expects an unsigned int.
If you pass an int and printf tries to retrieve a double, you invoke undefined behaviour.
If you pass an int and printf tries to retrieve an unsigned int, you invoke undefined behaviour.
Undefined behaviour may include (but is not limited to) printing strange values, crashing your program or (the most insidious of them all) doing exactly what you expect.
Source: n1570 (The final public draft of the current C standard)
You need to use a cast operator like this:
char c = 'z';
printf("%f %X", (float)c, c);
or
printf("%f %X", (double)c, c);
In Xcode, if I do not do this, I get the warning:
Format specifies specifies 'double' but the argument has type 'char', and the output is 0.000000.
I tried to print character as a float in printf and got output 0. What is the reason for this.
The question is, what value did you expect to see? Why would you expect something other than 0?
The short answer to your question is that the behavior of printf is undefined if the type of the argument doesn't match the conversion specifier. The %f conversion specifier expects its corresponding argument to have type double; if it isn't, all bets are off, and the exact output will vary.
To understand the floating point issue, consider reading: http://en.wikipedia.org/wiki/IEEE_floating_point
As for hexadecimal, let me guess.. the output was something like... 99?
This is because of encodings.. the machine has to represent information in some format, and usually that format entails either giving meanings to certain bits in a number, or having a table of symbols to numbers, or both
Floating points are sometimes represented as a (sign,mantissa,exponent) triplet all packed in a 32 or 64 bit number - characters are sometimes represented in a format named ASCII, which establishes which number corresponds to each character you type
Because printf, like any function that work with varargs, eg: int foobar(const char fmt, ...) {} tries to interpret its parameter to certain type.
If you say "%f", then pass c (as a char), then printf will try to read a float.
You can read more here: var_arg (even if this is C++, it still applies).

how does printf %n count characters? [duplicate]

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.:)

why printf behaves differently when we try to print character as a float and as a hexadecimal?

I tried to print character as a float in printf and got output 0. What is the reason for this.
Also:
char c='z';
printf("%f %X",c,c);
is giving some weird output for hexadecimal while output is correct when I do this:
printf("%X",c);
why is it so?
The printf() function is a variadic function, which means that you can pass a variable number of arguments of unspecified types to it. This also means that the compiler doesn't know what type of arguments the function expects, and so it cannot convert the arguments to the correct types. (Modern compilers can warn you if you get the arguments wrong to printf, if you invoke it with enough warning flags.)
For historical reasons, you can not pass an integer argument of smaller rank than int, or a floating type of smaller rank than double to a variadic function. A float will be converted to double and a char will be converted to int (or unsigned int on bizarre implementations) through a process called the default argument promotions.
When printf parses its parameters (arguments are passed to a function, parameters are what the function receives), it retrieves them using whatever method is appropriate for the type specified by the format string. The "%f" specifier expects a double. The "%X" specifier expects an unsigned int.
If you pass an int and printf tries to retrieve a double, you invoke undefined behaviour.
If you pass an int and printf tries to retrieve an unsigned int, you invoke undefined behaviour.
Undefined behaviour may include (but is not limited to) printing strange values, crashing your program or (the most insidious of them all) doing exactly what you expect.
Source: n1570 (The final public draft of the current C standard)
You need to use a cast operator like this:
char c = 'z';
printf("%f %X", (float)c, c);
or
printf("%f %X", (double)c, c);
In Xcode, if I do not do this, I get the warning:
Format specifies specifies 'double' but the argument has type 'char', and the output is 0.000000.
I tried to print character as a float in printf and got output 0. What is the reason for this.
The question is, what value did you expect to see? Why would you expect something other than 0?
The short answer to your question is that the behavior of printf is undefined if the type of the argument doesn't match the conversion specifier. The %f conversion specifier expects its corresponding argument to have type double; if it isn't, all bets are off, and the exact output will vary.
To understand the floating point issue, consider reading: http://en.wikipedia.org/wiki/IEEE_floating_point
As for hexadecimal, let me guess.. the output was something like... 99?
This is because of encodings.. the machine has to represent information in some format, and usually that format entails either giving meanings to certain bits in a number, or having a table of symbols to numbers, or both
Floating points are sometimes represented as a (sign,mantissa,exponent) triplet all packed in a 32 or 64 bit number - characters are sometimes represented in a format named ASCII, which establishes which number corresponds to each character you type
Because printf, like any function that work with varargs, eg: int foobar(const char fmt, ...) {} tries to interpret its parameter to certain type.
If you say "%f", then pass c (as a char), then printf will try to read a float.
You can read more here: var_arg (even if this is C++, it still applies).

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