C - int not-equal to printf? - c

What this C statement does?
i=!({ printf("%d\n",r); });
i and r are integers.
I'm trying to parse it using pycparser which doesn't recognize it and raises an error:
pycparser.plyparser.ParseError: :7:6: before: {
Thanks

It looks like it is using a GNU C extension that allows to write a block statement where an expression is expected. The value of the block statement is the value of the last expression of the block.
For example:
int x = ({ int a = 1; a+2; });
will initialize x with 3.
In your particular case the extension does not look very useful, because:
i=!({ printf("%d\n",r); });
is identical to:
i=!printf("%d\n",r);
I'm guessing that your original code is probably generated by some dark magic macro.
BTW, this code does not make much sense. It looks like it wants to check whether printf failed or suceeded in writing the text. But according to the specification, printf will return the number of bytes written if success or a negative value if error. So it will return 0 only if it writes 0 chars, and that will not happen with a \n at the end, and i will always end up being 0, either with or without error.

This is not standard C, but a GCC statement expression extension, which allows putting blocks in expressions and returns the value of the last statement in the block.
Because the block here has only one statement which is itself an expression, this is equivalent to:
i = !printf("%d\n",r);
This sets i to 1 if printf returned 0 (i.e. it succeeded but didn't print any characters), or 0 otherwise. Since this printf will always print at least two characters when it succeeds, i will always be 0.

Related

Recursive function for finding factorial of a number

I am getting an output of 24 which is the factorial for 4, but I should be getting the output for 5 factorial which is 120
#include <stdio.h>
int factorial(int number){
if(number==1){
return number;
}
return number*factorial(--number);
}
int main(){
int a=factorial(5);
printf("%d",a);
}
Your program suffers from undefined behavior.
In the first call to factorial(5), where you have
return number * factorial(--number);
you imagine that this is going to compute
5 * factorial(4);
But that's not guaranteed!
What if the compiler looks at it in a different order?
What it if works on the right-hand side first?
What if it first does the equivalent of:
temporary_result = factorial(--number);
and then does the multiplication:
return number * temporary_result;
If the compiler does it in that order, then temporary_result will be factorial(4), and it'll return 4 times that, which won't be 5!. Basically, if the compiler does it in that order -- and it might! -- then number gets decremented "too soon".
You might not have imagined that the compiler could do things this way.
You might have imagined that the expression would always be "parsed left to right".
But those imaginations are not correct.
(See also this answer for more discussion on order of evaluation.)
I said that the expression causes "undefined behavior", and this expression is a classic example. What makes this expression undefined is that there's a little too much going on inside it.
The problem with the expression
return number * factorial(--number);
is that the variable number is having its value used within it, and that same variable number is also being modified within it. And this pattern is, basically, poison.
Let's label the two spots where number appears, so that we can talk about them very clearly:
return number * factorial(--number);
/* A */ /* B */
At spot A we take the value of the variable number.
At spot B we modify the value of the variable number.
But the question is, at spot A, do we get the "old" or the "new" value of number?
Do we get it before or after spot B has modified it?
And the answer, as I already said, is: we don't know. There is no rule in C to tell us.
Again, you might have thought there was a rule about left-to-right evaluation, but there isn't. Because there's no rule that says how an expression like this should be parsed, a compiler can do anything it wants. It can parse it the "right" way, or the "wrong" way, or it can do something even more bizarre and unexpected. (And, really, there's no "right" or "wrong" way to parse an undefined expression like this in the first place.)
The solution to this problem is: Don't do that!
Don't write expressions where one variable (like number) is both used and modified.
In this case, as you've already discovered, there's a simple fix:
return number * factorial(number - 1);
Now, we're not actually trying to modify the value of the variable number (as the expression --number did), we're just subtracting 1 from it before passing the smaller value off to the recursive call.
So now, we're not breaking the rule, we're not using and modifying number in the same expression.
We're just using its value twice, and that's fine.
For more (much more!) on the subject of undefined behavior in expressions like these, see Why are these constructs using pre and post-increment undefined behavior?
How to find the factorial of a number;
function factorial(n) {
if(n == 0 || n == 1 ) {
return 1;
}else {
return n * factorial(n-1);
}
//return newnum;
}
console.log(factorial(3))

Figuring out what this function does?

I have to rewrite this for loop into a do while loop, but I can't figure out what this does. Please help
for(;; done = (int) sum == 5
{if (done) break;
sum += 2.6;}
Let's assume that the syntax error is resolved, so that the code reads
for(;; done = (int) sum == 5)
{
if (done) break;
sum += 2.6;
}
Now this code works as follows: the for loop has no initialization expression and no test expression, so it begins execution unconditionally. The first thing that happens is the "flag" done (an undefined object that I'm assuming is an int that may or may not be initialized to zero) is checked. If it's true (non-zero), the code breaks out of the for loop. if not, 2.6 (a double) is added to sum (an undefined object that I'm assuming is a double and that may or may not be initialized to a sensible value, or a number at all). When execution reaches the closing brace, the iteration statement in the for loop is executed, which compares sum to 5 (after converting sum to an integer value), and assigns the result of the comparison (i.e. 1 for true and 0 for false) to done.
Converting this to a while loop ought to be fairly straightforward. Simply execute these steps in order. Note that since the first piece of code to execute is checking if(done), the code more naturally lends itself to a simple while than a do-while loop.
Note that this would have been considerably clearer if you had defined the types of your variables, and provided initial values for them.

Why printf() gives a runtime error?

Why does this code below compiles and executes but doesn't print anything in output,
int i = 0;
printf(i = 0);
but this gives a runtime error,
int i = 0;
printf(i = 1);
int i = 0;
printf(i = 0);
The first argument to printf must be a char* value pointing to a format string. You gave it an int. That's the problem. The difference in behavior between printf(i = 0) and printf(i = 1) is largely irrelevant; both are equally wrong. (It's possible that the first passes a null pointer, and that printf detects and handles null pointers somehow, but that's a distraction from the real problem.)
If you wanted to print the value of i = 0, this is the correct way to do it:
printf("%d\n", i = 0);
You have a side effect in the argument (i = 0 is an assignment, not a comparison), which is legal but poor style.
If you have the required #include <stdio.h>, then your compiler must at least warn you about the type mismatch.
If you don't have #include <stdio.h>, then your compiler will almost certainly warn about calling printf without a declaration. (A C89/C90 compiler isn't strictly required to warn about this, but any decent compiler should, and a C99 or later compiler must.)
Your compiler probably gave you one or more warnings when you compiled your code. You failed to include those warnings in your question. You also failed to show us a complete self-contained program, so we can only guess whether you have the required #include <stdio.h> or not. And if your compiler didn't warn you about this error, you need to find out how to ask it for better diagnostics (we can't help with that without knowing which compiler you're using).
Expressions i = 0 and i = 1 in printf function will be evaluated to 0 and 1 (and i will be initialized to 0 and 1) respectively. So above printf statements after their expression evaluation will be equivalent to
printf(0); // To be clear, the `0` here is not a integer constant expression.
and
printf(1);
respectively.
0 and 1 both will be treated as address in printf statements and it will try to fetch string from these addresses. But, both 0 and 1 are unallocated memory addresses and accessing them will result in undefined behavior.
printf requires a const char * for input, whereas you're giving it an int
printf awaits a format string as its first argument. As strings (char*) are nothing else than pointers, you provide an address as the first parameter.
After an address and an integer are implicitly converted into each other,
printf(i = 0)
is (from the perspective of printf) the same as:
printf( 0 )
which is the same as
printf( NULL ) // no string given at all
If you provide 0 as parameter, printf will gracefully handle that case and don't do anything at all, because 0 is a reserved address meaning nothing at all.
But printf( 1 ) is different: printf now searches for a string at address 1, which is not a valid address for your program and so your program throws a segmentation fault.
[update]
The main reason why this works is a combination of several facts you need to know about how char arrays, pointers, assignments and printf itself work:
Pointers are implicitly convertible to int and vice versa, so the int value 17 for example gets converted to the memory address 0x00000011 (17) without any further notice. This is due to the fact that C is very close to the hardware and allows you to calculate with memory addresses. In fact, internally an int (or more specific: one special type of an integer) and a pointer are the same, just with a different syntax. This leads to a lot of problems when porting code from 32bit to 64bit-architecture, but this is another topic.
Assignments are different from comparations: i = 0 and i == 0 are totally different in meaning. i == 0 returns true when i contains the value 0 while i = 0 returns... 0. Why is that? You can concatenate for example the following variable assignments:
a = b = 3;
At first, b = 3 is executed, returning 3 again, which is then assigned to a. This comes in handy for cases like testing if there is more items in an array:
while( (data = get_Item()) )
This now leads to the next point:
NULL is the same as 0 (which also is the same as false). For the fact that integers and pointers can be converted into each other (or better: are physically the same thing, see my remarks above), there is a reserved value called NULL which means: pointing nowhere. This value is defined to be the virtual address 0x00000000 (32bit). So providing a 0 to a function that expects a pointer, you provide an empty pointer, if you like.
char* is a pointer. Same as char[] (there is a slight logical difference in the behaviour and in the allocation, but internally they are basically the same). printf expects a char*, but you provide an int. This is not a problem, as described above, int will get interpreted as an address. Nearly every (well written) function taking pointers as parameters will do a sanity check on these parameters. printf is no exclusion: If it detects an empty pointer, it will handle that case and return silently. However, when providing something different, there is no way to know if it is not really a valid address, so printf needs to do its job, getting interrupted by the kernel when trying to address the memory at 0x00000001 with a segmentation fault.
This was the long explanation.
And by the way: This only works for 32-bit pointers (so compiled as 32-bit binary). The same would be true for long int and pointers on 64-bit machines. However, this is a matter of the compiler, how it converts the expression you provide (normally, an int value of 0 is implicitly cast to a long int value of 0 and then used as a pointer address when assigned, but vice versa won't work without an explicit cast).
Why does this code below compiles and executes but doesn't print anything in output?
printf(i = 0);
The question embodies a false premise. On any modern C compiler, this clearly-erroneous code generates at least one error.

Why a syntax like "a=b--- // a newline, line ends without ;" does not produce syntax error?

What is the output of this program and how?
#include<stdio.h>
int main(){
int a=0,b=10;
a=b---
printf("the value of b=%d",b);
printf("the value of a=%d",a);
return 0;
}
In your code, writing
a=b---
printf("the value of b=%d",b);
is same as
a = b---printf("the value of b=%d",b);
which is an expression with undefined behavior, as an attempt is made to change and use the value of variable b in two subexpressions without a sequence point in between. Hence, the output of this code cannot be justified.
Without the above problem, in general, the syntax is similar to
x = (y--) - (<return value of printf() call>)
which is a perfectly valid syntax.
Note:
Why a = b---<something> is treated as a = (b--) - <something> and not a = b - -- <something> is due to the maximal munch rule.
Strictly speaking, as others have said since this is undefined behaviour, the result could be anything . And while they're right, it doesn't explain why you get this specific answer in this specific compiler.
In practice b will usually be printed as 9, or 10 depending on whether the compiler does the decrememnt first or the printf first.
printf returns the number of characters printed. Which I think is 16 or 17 in this case.
So this is like writing a = (b--) - 16; b is 10 before the decrement and it's a post decrement so this is the value used.

C equivalent operator creating confusion

Program 1:
#include<stdio.h>
void main()
{
int i=55;
printf("%d %d %d %d\n",i==55,i=40,i==40,i>=10);
}
Program 2:
#include<stdio.h>
void main(){
int i = 55;
if(i == 55) {
printf("hi");
}
}
First program give output 0 40 0 1 here in the printf i == 55 and output is 0 and in the second program too i ==55 and output is hi. why
In the first example, the operators are evaluated in reverse order because they are pushed like this on the stack. The evaluation order is implementation specific and not defined by the C standard. So the squence is like this:
i=55 initial assignment
i>=10 == true 1
i==40 == false (It's 55) 0
i=40 assignment 40
i==55 == false (It's 40) 0
The second example should be obvious.
There's no guarantee about the order in which arguments to a function are evaluated. There's also no sequence point between evaluating the different arguments to the function.
That means your first call gives undefined behavior, because it both uses the existing value of i and writes a new value to i without a sequence point between the two.
In a typical case, however, each argument to a function will be evaluated as a separate expression, with no interleaving between them. In other words, the compiler will impose some order to the evaluation, even though the standard doesn't require it to do so.
In the specific case of a variadic function, the arguments are typically pushed onto the stack from right to left, so the first argument (the format string) will be at the top of the stack. This makes it easy for printf to find the format string, and then (based on that) retrieve the rest of the arguments from further down the stack.
If (as is fairly typical) the arguments are evaluated immediately prior to being pushed on the stack, this will lead to the arguments being evaluated from right to left as well.
Functions with a fixed number of arguments aren't evaluated from right to left nearly as often, so if (for example) you wrote a small wrapper taking a fixed number of arguments, that then passed those through to printf, there's a greater chance that i would have the value 55 when the first argument to printf is evaluated, so that would produce a 1 instead of a 0.
Note, however, that neither result is guaranteed, nor is any meaningful result guaranteed--since you have undefined behavior, anything is allowed to happen.
The arguments of printf are evaluated from right to left here (this is unspecified behavior, but the behaviour you noticed shows that at least the first argument is evaluated after the second). In your argument list there ist i=40, which sets the value to 40. Therefore the first printed argument is false (0).
The function printf evaluates the expressions in implementation specific manner, in this case from right to left. Hence the output:
i==55(0),i=40(Assignment),i==40(0),i>=10(1)
The reason is that the order in which the arguments to the printf function (actually any function) are evaluated, before being passed to the function, is not defined by the C standard.
The problem is not with your understanding of the == operator.
Edit: Although many authors are pointing out that printf typically evaluates its arguments from right-to-left (which I wasn't aware of), I would say it's probably a bad idea to write code that depends on this, as the language does not guarantee it, and it makes the code much less readable. Nevertheless is is a good factoid to know in case you come across it in the wild.
In the first program: The order of evaluation of the printf() arguments is implimentation defined. So this program doesn't give the same result on different implimentation of printf() So there is no guarantee about what the program will result.
It could output 0 40 0 1 as it could output 1 40 1 1 if the order of evaluation is reversed.

Resources