How does the following code works printf("%c")? - c

I wanted to know how the following program is working?
#include <stdio.h>
int main(void) {
while(1){
if(printf("%d",printf("%c")))
break;
else
continue;
}
return 0;
}
I did not know how the part printf("%c") is working and therefore the whole program.I am aware of writing something like printf("%c", 'a'); like that but how is it working without providing the character to be printed? My question is what does the following program prints and how does it prints so?
I have tried to run the program, sometimes it prints nothing, but sometimes it is printing some random character followed by 1. I am not able to get how it is working, can someone please explain what is going behind the code and how it is printing that random characters, and why there is one at the end?
Here are some output I am getting

Welcome to Undefined Behavior. You fail to have sufficient number of arguments for the format you specify, e.g.
C11 Standard - 7.21.6.1 The fprintf function(p2) "If there are insufficient arguments for the format, the behavior is undefined." 7.21.6.1(p9) "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."

A cool wrong program you have.
printf("%c") attempts to print a single character that is supposed to be the second parameter. However, since you have never passed the second parameter, the function prints whatever is in the register that was supposed to have the second parameter. In other words, some random character. However, it prints one character and returns 1: the number of characters printed.
That 1 is in turn printed by printf("%d",printf("%c")). Now you have a random character followed by 1, and since the outer printf also prints one character, it returns 1.
Finally, if(printf("%d",printf("%c"))) interprets that later 1 as true and breaks the loop.

This is about format bugs.
Look at this code, when execute printf("%d", 123), the program will push number 123 onto the stack, and then push string "%d", when printf meets "%d", it will read the value on the top of the stack, so printf find the number 123.
Now look at this code, printf("%c"), program will push string "%c" onto the stack, and try to read value on the top of the stack, you haven't push a value for printf, so printf will still find value, but the value is random, so you might get a random value.

Related

Use sscanf to process variable-format output

This is a program ,15.5,in the book called Pointers On C.I can't understand what this program want to do.
#include<stdio.h>
#include<stdlib.h>
#define DEFAULF_A 1
#define DEFAULF_B 2
void function(char *buffer)
{
int a,b,c;
if(sscanf(buffer,"%d %d %d",&a,&b,&c)!=3)
{
a=DEFAULF_A;
if(sscanf(buffer,"%d %d",&b,&c)!=2)
{
b=DEFAULF_B;
if(sscanf(buffer,"%d",&c)!=1)
{
fprintf(stderr,"Bad input:%s",buffer);
exit(EXIT_FAILURE);
}
}
}
}//***the title of the program is Use sscanf to process variable-format output***
If I suppose the first three number in buffer is 1,2 and 3.
List item
The sscanf at the second if assigns 1 to B that should have been assigned to A and assigns 2 to C that should have been assigned to B.So why not just throw out the &c and leave the &a in sscanf,like this
c=DEFAULF_A;
if(sscanf(buffer,"%d %d",&a,&b)!=2)
List item
And why does the exit(EXIT_FAILURE) appear in the third if?When the exit(EXIT_FAILURE) appear in the third if,it mean there is a problem with the first read and the second and the third reads don't know.But when it comes this case sscanf(buffer,"%d %d %d",&a,&b,&c)!=3,the program is also wrong.
List item
So what this program want to do?
Due to I just started to learn CS,I only konw a little about C language,and lack other basic computer knowledge,please answer in a way that is easy to understand.Thanks in advance.
This is a example in Pointers On C .This program might correspond to this sentence that "the latter is used to convert the expected number of values.
[] The sscanf at the second if assigns 1 to B that should have been assigned to A and assigns 2 to C that should have been
assigned to B.So why not just throw out the &c and leave the &a in
sscanf,like this
c=DEFAULF_A;
if(sscanf(buffer,"%d %d",&a,&b)!=2)
Because that's (apparently) not the desired behavior. The program is assigning read values to the rightmost subset of variables (a, b, c), so if only two values are provided then they go to b and c, and if only one is provided then it goes to c. The variables that don't get read values assigned to them are assigned default values instead. Your proposed alternative does not achieve the same thing.
And this is in fact the distinguishing characteristic of the function presented -- the "trick", if you will. It would indeed be simpler to write a straight left-to-right style matchup of values to variables.
Nevertheless, the function is needlessly complicated. Myself, I would not write it with three separate sscanf calls, because you can get everything you need from just one. I would write the function something like this:
#define DEFAULT_A 1
#define DEFAULT_B 2
void function(char *buffer) {
int a, b, c, num_fields;
num_fields = sscanf(buffer, "%d %d %d", &a, &b, &c);
switch (num_fields) {
case 3:
// three values read and assigned. nothing to see here.
break;
case 2:
// only two values read (into variables 'a' and 'b')
// shift them to the correct variables and assign a default to 'a'
c = b;
b = a;
a = DEFAULT_A;
break;
case 1:
// only one value read (into variable 'a')
// shift it to the correct variable and assign defaults to the others
c = a;
b = DEFAULT_B;
a = DEFAULT_A;
break;
default:
fprintf(stderr, "Bad input: %s\n", buffer);
exit(EXIT_FAILURE);
}
}
[] And why does the exit(EXIT_FAILURE) appear in the third if?When the exit(EXIT_FAILURE) appear in the third if,it mean there is
a problem with the first read and the second and the third reads don't
know.But when it comes this case sscanf(buffer,"%d %d %d",&a,&b,&c)!=3,the program is also wrong.
The return value of sscanf reports on two things:
how many scanf directives resulted in values being successfully read from the input, converted to the indicated data type, and assigned to variables; and
whether any kind of system error was encountered (very unlikely for sscanf(), but this is shared with scanf(), for which it is a genuine possibility).
You seem to have the second one in mind, but it is the first that the program is mainly relying upon. It is using the return value to determine how many of the variables were assigned values. That the first attempt does not assign all three does not imply that the second will not assign two, or the third, one. But of course you're right that the program is somewhat redundant. As I demonstrate above, only one sscanf() call is needed.
[] So what this program want to do?
Nitpick: it's just one function, not a complete program.
Technically, because it doesn't do anything with the values it parses out of the string, all it does is report on whether the string pointed to by the function argument starts with a text representation of at least one decimal integer, optionally preceded by any number of whitespace characters (spaces, tabs, etc.). If so, it prints nothing. If not, it prints an error message.
But what you're probably looking for is the explanation I provided in response to your first numbered question.
Seeing how you are essentially asking 'What does this program' do: It is essentially performing a 'default initialization for not entered values'.
Another (more efficient) way to achieve (much) the same thing is:
#include<stdio.h>
#include<stdlib.h>
#define DEFAULF_A 1
#define DEFAULF_B 2
void function(char *buffer)
{
int a,b,c;
switch (sscanf(buffer,"%d %d %d",&a,&b,&c))
{
case 1:
b = DEFAULF_B; //Only one has been entered, assign default to 'b'.
//Falls through
case 2:
c = DEFAULF_A; //Only two have been entered, assign default to 'c'.
//Falls through.
case 3: break; //All three have been entered, do nothing.
default:
exit(EXIT_FAILURE); //None have been entered -> Abort the program.
break;
}
}
If buffer contained 3 numbers, all three numbers are kept and no defaults are applied.
If buffer contained 2 numbers, the two numbers are kept (in your code that's b and c, in mine it's a and b) and DEFAULF_A is assigned to the remaining variable.
If buffer contained 1 number, that number is kept (c for you, a in my example) and the other two get assigned DEFAULF_A and DEFAULF_B respectively.
If buffer contained no number at all, your program gets terminated with the return code 'EXIT_FAILURE', which a calling program could fetch.
The program examines contents from a buffer, and tries to read three values from it, for example:
1 2 3
If the first sscanf finds three numbers, it reads them all. If only two are found, it assigns default value to a and tried to read two numbers. If only one is found, it assigns default value to b and tries to read one number. If there are no numbers, the program exits, because there is no default value for c.
So if we reach exit(), it means there were neither 3, 2, or 1 numbers in the buffer. If one of the if clauses succeeded, further ones are not executed.
It is important to realize that sscanf always starts from the beginning of the buffer. So if it reads for example 1 2 in the first call, but cannot find the third one, the buffer still contains the same data during the second call, and two numbers can be read.
Regarding your question 1: Why are two numbers considered as "b and c", rather than "a and b"? This is simply the way the programmer wanted the program to work. They could have as easily set a default value for c and considered the two numbers as "a and b".
Regarding your question 2: What if the output is completely invalid, and the third read will fail? In that case, we know that the first and second reads will fail as well, so we can safely put the error handling after the third one.

Unexpected output on using puts() and printf() function

I'm trying to run a basic code on my Dev C++ IDE, but it gives an expected output-
printf("%d", printf("stackoverflow1"));
printf("%d", puts("stackoverflow2"));
puts(printf("stackoverflow3"));
the expected output should be:
stackoverflow114stackoverflow2
14stackoverflow314
but the output I'm getting is:
stackoverflow114stackoverflow2
0stackoverflow3
Can someone explain the inconsistency in the output ? I know that puts return a non negative number but why I'm getting a '0' everytime. Also in the last statement why is puts not printing the no of characters printed by printf ?
puts(), as you mentioned, only has to return a non-negative number on success. This means the compiler you are using gets to decide what is returned, as long as it follows this. Your compiler appears to have chosen 0.
as 2501 mentioned, passing puts(const char * p ) an int is illegal, your compiler should have complained about it. puts() is supposed to print starting from p until it reaches a '\0' char, so the input has to be a pointer to a '\0' terminated string
You have undefined behavior. puts() takes a const char* argument yet you pass it an int.
puts(printf("stackoverflow3"));
Enable warnings on your compiler and your code won't even compile.
printf("%d", printf("stackoverflow1"));
Printf returns an int (how much chars are printed = 14). Because the arguments of the outer printf have to be evaluated before the outer one can be evaluated, the string printed will bee "stackoverflow114"
printf("%d", puts("stackoverflow2"));
puts returns a "nonnegative value" (this is the only guarantee, the standard gives to you). In your case the nonnegative value is the int 14. The string "stackoverflow2\n" is printed by puts and the 14 is printed by printf.
puts(printf("stackoverflow3"));
puts takes an const char* as an argument and printf returns the number of chars printed (which is 14, again). Since puts takes a pointer, it may interpret the memory at address 14 as a string and output it (it might cancel compilation, too - most compilers will be 'glad' and cast this for you, along with a warning). This string seems to be empty (this might be sort of random). This line thus only prints "stackoverflow3" (in your case) and the outer puts only prints a random string (in your case "").

Why output length is coming 6?

I have written a simple program to calculate length of string in this way.
I know that there are other ways too. But I just want to know why this program is giving this output.
#include <stdio.h>
int main()
{
char str[1];
printf( "%d", printf("%s", gets(str)));
return 0;
}
OUTPUT :
(null)6
Unless you always pass empty strings from the standard input, you are invoking undefined behavior, so the output could be pretty much anything, and it could crash as well. str cannot be a well-formed C string of more than zero characters.
char str[1] allocates storage room for one single character, but that character needs to be the NUL character to satisfy C string constraints. You need to create a character array large enough to hold the string that you're writing with gets.
"(null)6" as the output could mean that gets returned NULL because it failed for some reason or that the stack was corrupted in such a way that the return value was overwritten with zeroes (per the undefined behavior explanation). 6 following "(null)" is expected, as the return value of printf is the number of characters that were printed, and "(null)" is six characters long.
There's several issues with your program.
First off, you're defining a char buffer way too short, a 1 char buffer for a string can only hold one string, the empty one. This is because you need a null at the end of the string to terminate it.
Next, you're using the gets function which is very unsafe, (as your compiler almost certainly warned you about), as it just blindly takes input and copies it into a buffer. As your buffer is 0+terminator characters long, you're going to be automatically overwriting the end of your string into other areas of memory which could and probably does contain important information, such as your rsp (your return pointer). This is the classic method of smashing the stack.
Third, you're passing the output of a printf function to another printf. printf isn't designed for formating strings and returning strings, there are other functions for that. Generally the one you will want to use is sprintf and pass it in a string.
Please read the documentation on this sort of thing, and if you're unsure about any specific thing read up on it before just trying to program it in. You seem confused on the basic usage of many important C functions.
It invokes undefined behavior. In this case you may get any thing. At least str should be of 2 bytes if you are not passing a empty string.
When you declare a variable some space is reserved to store the value.
The reserved space can be a space that was previously used by some other
code and has values. When the variable goes out of scope or is freed
the value is not erased (or it may be, anything goes.) only the programs access
to that variable is revoked.
When you read from an unitialised location you can get anything.
This is undefined behaviour and you are doing that,
Output on gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 is 0
For above program your input is "(null)", So you are getting "(null)6". Here "6" is the output from printf (number of characters successfully printed).

Why char value assignment to float is not working

Note:This question is very simple but when I am searching in Google I haven't got any clear clarification.
I have following program
int main()
{
float c;
scanf("%f",&c);
printf("%f",c);
}
o/p
when I am giving a int value (e,g - 9) it is showing it as 9.000000
but when I am giving char value like 'a' it is not showing and showing 0.000000.I know the memory representation of float is totally different from int but then how when I am giving int value (9) it is showing but when I am giving char (a) which is also an int (97) is not showing.
How it is happening. What is the memory representation during char assignment.
Note that there are no chars here anywhere in your code.
This is the way scanf is supposed to work. If you check the return value from scanf (like you should be!) you'll probably see that it's returning 0, meaning no items were matched.
When you give scanf() a "%f" format string, that means "I want you to try and get me a floating point number. When you provide input like 'a', it's not going to match anything, because 'a' is not a valid floating-point number.
http://www.cplusplus.com/reference/cstdio/scanf/
First, you usually should end your printf format string with a newline \n or else call fflush.
Then, you should read the documentation on scanf i.e. its man page scanf(3)
It can fail, and it returns the number of successful matches:
Return Value
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in
the event of an early matching failure.
The value EOF is returned if the end of input is reached before either
the first successful conversion or a matching failure occurs. EOF is
also returned if a read error occurs, in which case the error
indicator for the stream (see ferror(3)) is set, and errno is set
indicate the error.
A failure is happening when you type an input letter a against a %f conversion specification. In your case the c variable is left unchanged (i.e. "uninitialized").
You should test the result of scanf (it is <=0 on failure in your case).
scanf in the form you wrote it will try to find and read numbers (int/float) up to the first non numerical character (newline, space, any letter). Letters are ints, but this is because of the scanf and the way it should behave. Read up the docs.

Please explain this ambiguity in C

When I am compiling this program I am getting some random number as output.. In Cygwin the output is 47 but in RHEL5, it is giving some negative random numbers as output.
Can anyone tell me the reason?
Code:
main()
{
printf("%d");
}
This program provokes undefined behavior since it does not follow the rules of C. You should give printf one argument per format specifier after the format string.
On common C implementations, it prints whatever happens to be on the stack after the pointer to "%d", interpreted as an integer. On others, it may send demons flying out of your nose.
It is Undefined Behaviour.
On 3 counts:
absence of prototype for a function taking a variable number of arguments
lying to printf by telling it you are sending 1 argument and sending none
absence to return a value from main (in C99 a return 0; is assumed, but your code definitely isn't C99)
Anything can happen.
printf expects a second argument, so it reads whatever happens to be on the stack at that location. Essentially it's reading random memory and printing it out.

Resources