understanding weird output of printf function - c

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
%%

Related

Trying to understand printf a pointer with a char specifier (%c)

#include<stdio.h>
void main()
{
int n = 2;
printf("%c",&n);
}
Output: L
On using %d it of course gives the address of variable n but why is it outputting L on using %c?
It is undefined behaviour because you have used wrong format specifier.
C11 Standard: 7.21.6.1 : paragraph 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.
It means anything can happen if printf is called with a wrong format specifier.
As the other answer of rsp said the behaviour is undefined and anything could happen.
In your case the following happens:
It reads one byte of &n because a character is of one byte size which is mostly 8 bits long, see CHAR_BIT explanation on SO. Then it prints it as character.
This byte could be the first byte of &n if the types int* and int are the same at your machine. That would mean that your variable n lies at address 0x48... (big-endian) or 0x...48 (little-endian) as 0x48 is H in the Ascci code. I assume that your program is using Ascii for encoding which doesn't necessarily have to.
(You changed the character from H to L but I leave this answer as it is.)
Also this byte can lie somewhere in the middle of the &n if an int* exceeds the size of an int at your system.
You should compile with more warnings enabled for example -Wall in gcc and you will get:
warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
In the case you cast that value to a char the behaviour will be well defined but rely on the implementation as a cast of a pointer type to an integer is implementation defined.
Nevertheless what you're doing makes no sense also with a cast it will not do.
It's because you told printf() function to show the first 1-byte of int n's address as a char.

Why only multiple "%" is accepted by printf?

Following program give the output %%. Why?
#include <stdio.h>
int main() {
//code
printf("%%%%");
return 0;
}
output:
%%
TL;DR a % is a valid conversion specifier for printf().
Quoting C11, chapter §7.21.6.1, for conversion specifiers,
Each conversion specification is introduced by the character %. After the %, the following
appear in sequence:
.....
— A conversion specifier character that specifies the type of conversion to be applied.
and, from paragraph 8, for % as a conversion specifier character
for % conversion specifier
% A % character is written. No argument is converted. The complete
conversion specification shall be %%.
Your code has a pair of %%s.
Printf function's first argument is a format represented by a char*, it's not a string.
That's why for printing an int,for example, you have to write "%d". So % is a special character, if you only write % as format, the compiler won't be happy because it is waiting for something after the % (either d, p, x, s, f, ...).
However, by writing %% it means "Print me one escaped %". That's why %%%% prints %%
EDIT: If you want a function that prints exactly what you give, you can use write:
char* mystr = "%%%%";
write(STDOUT_FILENO, mystr, strlen(mystr));

What does a # sign after a % sign in a scanf() function mean?

What does the following code mean,in C
scanf("%d%#d%d",&a,&b,&c);
if given values 1 2 3 it gives output as 1 0 0
P.S- I know it is used with printf() statement but here in scanf() statement it gives random behaviour.
TL;DR; - A # after a % sign in the format string of scanf() function is wrong code.
Explanation:
The # here is a flag character, which is allowed in fprintf() and family, not in fscanf() and family.
In case of your code, the presence of # after % is treated as invalid conversion specifier. As per 7.21.6.2,
If a conversion specification is invalid, the behavior is undefined
So, your code produces undefined behaviour.
Hint: you can check the return value of scanf() to check how many elements were "scanned" successfully.
However, FWIW, using # with %d in printf() also is undefined behaviour.
Just for reference: As per the C11 standard document , chapter §7.21.6.1, flag characters part, (emphasis mine)
#
The result is converted to an ‘‘alternative form’’. For o conversion, it increases the precision, if and only if necessary, to force the first digit of the result to be a zero (if the value and precision are both 0, a single 0 is printed). For x (or X) conversion, a nonzero result has 0x (or 0X) prefixed to it. For a, A, e, E, f, F, g, and G conversions, the result of converting a floating-point number always contains a decimal-point character, even if no digits follow it. (Normally, a decimal-point character appears in the result of these conversions only if a digit follows it.) For g and G conversions, trailing zeros are not removed from the
result. For other conversions, the behavior is undefined.
According to the Standard, the use of # is illegal.
Its use makes your program invoke Undefined Behaviour.
Of course, if your implementation defines it, it is defined behaviour for your implementation and it does what your documentation says.

printf value in union depending on format

It is possible to scanf values into a union depending on the format specifier.
union {
int i;
double f;
} u;
scanf("%lf", &u.i); // implicitly scan the double
printf("%lf", u.f); // explicitly print the double
This works because scanf takes pointers as arguments, and all elements in the union are aligned, (void*)&u.i == (void*)&u.f.
Is it possible to change the printf line in a way that does the same thing, picking the correct value to print from the union based on the format, without accidentally slicing some of the possible values?
printf("%lf", ???); // implicitly print the double
printf cannot infer the type of the arguments passed to it. The argument will be interpreted as per the corresponding conversion specifier in the format string. Therefore, the arguments must correspond properly to their respective conversion specifiers. Quoting C11 standard § 7.21.6.1 ¶9 about fprintf
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.
Again quoting from the C11 standard § 7.21.6.2 ¶13 about fscanf
If a conversion specification is invalid, the behavior is undefined.
Therefore, the following call to scanf invokes undefined behaviour because u.i is of type int but %lf conversion specifier means you are reading a double.
scanf("%lf", &u.i);
Please read these -
What happens when I use the wrong format specifier?
Wrong format specifiers in scanf or printf
Also, it's undefined behaviour to access the field of a union which was not most recently written.
union {
int i;
double f;
} u;
// undefined behaviour. u.i is of type int but %lf
// means scanf will read a double
scanf("%lf", &u.i);
// undefined behaviour because reading the field u.f
// but the last written field is u.i
printf("%lf", u.f);
No, you can't do that.
There's no indirect printf() format specifier, and different members of the union can have different size and thus be handled differently as a varargs parameter.
Even if there was a way to say "pointer to integer" instead of just "integer", there would still of course be no way to have printf() decide between "pointer to integer" and "pointer to double" based only on that pointer value.
If I understood you correctly, you'd like something like:
printf("%>g\n", &u); /* prints the double */
printf("%>d\n", &u); /* prints the int */
Where I invented (!) the > format modifier to say "the argument is a pointer to the corresponding data type, i.e. >g is "pointer todouble`". Sadly this is not standard. You can of course implement this yourself.

problem with function printf()

Here is my program:
#include <stdio.h>
int main()
{
int a=0x09;
int b=0x10;
unsigned long long c=0x123456;
printf("%x %llx\n",a,b,c);//in "%llx", l is lowercase of 'L', not digit 1
return 0;
}
the output was:
9 12345600000010
I want to know:
how function printf() is executed?
what will happen if the number of arguments isn't equal to that of formats?
please help me and use this program as an example to make an explanation.
The problem is that your types don't match. This is undefined behavior.
Your second argument b does not match the type of the format. So what's happening is that printf() is reading past the 4 bytes holding b (printf is expecting an 8-byte operand, but b is only 4 bytes). Therefore you're getting junk. The 3rd argument isn't printed at all since your printf() only has 2 format codes.
Since the arguments are usually passed consecutively (and adjacent) in memory, the 4 extra bytes that printf() is reading are actually the lower 4 bytes of c.
So in the end, the second number that's being printed is equal to b + ((c & 0xffffffff) << 32).
But I want to reiterate: this behavior is undefined. It's just that most systems today behave like this.
If the arguments that you pass to printf don't match the format specification then you get undefined behavior. This means that anything can happen and you cannot reason about the results that you happen to see on your specific system.
In your case, %llx requires and argument of type unsigned long long but you supplied an int. This alone causes undefined behaviour.
It is not an error to pass more arguments to printf than there are format specificiers, the excess arguments are evaluated but ignored.
printf() increases a pointer to read an argument at a time according to the format. If the number of formatting arguments is larger than the number of parameters, then printf() will output data from unknown memory locations. But if the number of parameters is larger than the number of formatting arguments, then no harm was done. E.g. gcc will warn you if the number of formatting arguments and parameters don't match.

Resources