I'm wondering what the following statement will print in C?
printf("hello\n") || (printf("goodbye\n") || printf("world\n"));
I'm usually accustomed to using "cout" to print something in C. Also I'm confused about the pipe and double pipe operators used this way. Thank you!
First, cout is a C++ invention, never made it back to C, and never will.
Next, printf returns the number of printed characters, so the first call returns non-zero.
As || is short-circuiting boolean-or, none of the following printf-calls will be done.
(| is bitwise-or, and thus not short-circuiting. Added because you are talking about single pipes and #Leeor linked such a question.)
Endresult: hello\n is printed: 5 characters+newline (will be translated, as stdin is text-mode (identity-transformation on Unixoids)).
7.21.6.3 The printf function
Synopsis
#include <stdio.h>
int printf(const char * restrict format, ...);
Description
2 The printf function is equivalent to fprintf with the argument stdout interposed
before the arguments to printf.
Returns
3 The printf function returns the number of characters transmitted, or a negative value if
an output or encoding error occurred.
6.5.12 Bitwise inclusive OR operator
Synopsis
[...]
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The usual arithmetic conversions are performed on the operands.
4 The result of the | operator is the bitwise inclusive OR of the operands (that is, each bit in
the result is set if and only if at least one of the corresponding bits in the converted
operands is set).
6.5.14 Logical OR operator
Synopsis
[...]
Constraints
2 Each of the operands shall have scalar type.
Semantics
3 The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
4 Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the
second operand is evaluated, there is a sequence point between the evaluations of the first
and second operands. If the first operand compares unequal to 0, the second operand is
not evaluated.
It will print:
hello\n (that is, hello and a newline, not the literal "\n".)
printf returns the number of characters printed to the console. The || is a short-circuiting "or", which means: do the first thing, then if the first thing returned "false", do the next thing. At the end, return back whether any of the things you did returned "true".
In c, an int is considered "true" if it is any value other than 0, and all three of those printf calls print more than 0 characters, so it will run the first one, which returns (a value logically equivalent to) true, so it will stop execution of that line and go onto the next.
Of course, there's no reason to ever write code like that... there are sometimes reasons to use short-circuiting boolean operators with functions that have side-effects (like printing to the console), but I can't think of a reason you'd ever need to short-circuit where the functions you were calling were being passed constants and you always knew exactly what result you would get from them.
Also, yes, as written there's a compile error because of an extra open-parenthesis before your second printf. But ignoring that.
It prints "hello" only!
http://www.compileonline.com/compile_c_online.php
#include <stdio.h>
#include <string.h>
main()
{
printf("hello\n") || (printf("goodbye\n") || printf("world\n"));
}
Related
How the logical NOT operator ! actually works in c?
How it turns all non-zero int into 0 and vice-versa?
For example:
#include <stdio.h>
void main() {
if(!(-76))
printf("I won't print anything");
if(!(2))
printf("I will also not print anything");
}
doesn't print anything, which could mean -76 and 2 was turned into zero...
So, I tried this:
#include <stdio.h>
void main() {
int x = !4;
printf("%d", x);
}
which indeed printed 0
and now I don't get how, is it flipping all the bits to 0 or what?
Most CPU architectures include an instruction to compare to zero; or even check the result against zero for most operations run on the processor. How this construct is implemented will differ from compiler to compiler.
For example, in x86, there are two instructions: JZ and JNZ: jump zero and jump not zero, which can be used if your test is an if statement. If the last value looked at was zero, jump (or don't jump) to a new instruction.
Given this, it's trivial to implement int x = !4; at assembly level as a jump if 4 is zero or not, though this particular example would be likely calculated at compile time, since all values are constant.
Additionally, most versions of the x86 instruction set support the SETZ instruction directly, which will set a register directly to 1 or 0, based on whether the processors zero flag is currently set. This can be used to implement the logical NOT operation directly.
6.5.3.3 Unary arithmetic operators
Constraints
1 The operand of the unary + or - operator shall have arithmetic type; of the ~ operator, integer type; of the ! operator, scalar type.
Semantics
...
5 The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).
C 202x Working Draft
So, that's what language definition says should happen; if the expression x evaluates to non-zero, then the expression !x should evaluate to zero; if x evaluates to zero, then !x should evaluate to 1. The bits of the operand are not affected.
How that's accomplished in the machine code is up to the specific implementation; it depends on the available instruction set, the compiler, and various other factors such that no one answer works everywhere. It could translate to a branch statement, it could take advantage of specialized instructions, etc.
This question already has answers here:
C comma operator
(4 answers)
What does the comma operator , do?
(8 answers)
Closed 7 years ago.
I saw this in an exam and when I tried it out I was surprised. I tried it online and it works too. So I think it is the C language.
Why is that working? What is the use case for such an assignment syntax?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int i = (1,2,3,4,5);
printf("%d", i);
return 0;
}
These are not "multiple integers", but a comma operator. The whole parenthesised part is a single expression with each sub-expression (separated by commas) evaluated strictly from left to right. The results of all but the rightmost subexpression are ignored. The result of the whole expression is that of the last (rightmost) expression. Here it is the integer value 5.
Note that this operator is mostly used where only a single expression is allowed to add further side-effects. E.g. in a loop like:
int cnt = 0;
for ( const char *cp = "Hello" ; *cp != '\0' ; cp++, cnt++ ) ;
This counts the number of characters in a C-string, incrementing the pointer and cnt after each iteration. The results are ignored here.
So, this is in no way related to tuples or similar like in Python. There are actually no cases the usage of this operator is unavoidable and it should be used with caution — and some coding standards forbid its usage.
That's the comma operator at work. It evaluates the expression on its left-hand side, creates a sequence point, discards the value of the expression, then evaluates the expression on the right-hand side, and returns that as the value. When there are multiple expressions as in the example, then each is evaluated in turn and only the last is kept. With the sample, the compiler does the evaluation because every value is known at compile time. Note that the argument list to a function is not a use of the comma operator.
That isn't a valid use-case for the comma operator. What might be a more nearly valid use-case would be some operations with side-effects (such as function calls) that need to be sequenced and the final value assigned:
int i = (getchar(), getchar(), getchar());
This sets i to the third character in standard input, or EOF if there are not three characters left in the standard input to be read. Still not a realistic use-case, but better than assigning a list of constants.
In addition to the other answers, you need to watch for instances where a , is the comma operator as opposed to when it is a separator. For example, the following is invalid:
int i = 1,2,3,4,5;
In this case, the , is a separator between variable declarations. It declares i as an int and initializes it to 1, then it attempts to parse 2 as a variable name, which fails.
It works because you're using the "comma operator", which evaluates the subexpressions on the left and right, and has the value from the right-hand expression.
So in (1,2,3,4,5), 1 is evaluated and the result is discarded, then 2,3,4,5... in which (because of the next comma) 2 is evaluated and the result discarded, then 3,4,5... in which 3 is evaluated and discarded, then 4,5... in which 4 is evaluated and discarded, then 5 which becomes the result of the expression.
As for when it's useful, mainly as a shortcut when you need to evaluate several (sub)expressions for their side effects but aren't interested in their values (except maybe the last one). It's sometimes convenient in for loop expressions, such as when incrementing two variables:
for (i=0,j=1; j < len; i++,j++) {
..where it appears in both the initialization expression and the loop expression.
Why is that working?
Because its a valid C syntax. The comma in (1,2,3,4,5) are comma operator
C11: 6.5.17 Comma operator
Syntax
1 expression:
assignment-expression
expression , assignment-expression
Semantics
2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.114)
What is the use case for such an assignment syntax?
See the example below
3 EXAMPLE As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second
expression of a conditional operator in such contexts. In the function call
f(a, (t=3, t+2), c)
the function has three arguments, the second of which has the value 5.
Imagine i have the following piece of C-code where foo() produces a side effect and returns an integer:
if(bar) {
foo();
return 0;
}
Now, say I really like making my code compact, possibly at the reader's expense, and I change it into this:
if (bar)
return foo() && 0;
Can I be sure these two pieces of code will produce the same behavior, or would I risk the call to foo() not being executed due to possible compiler optimizations or something like that, thus not producing the desired side-effect?
NOTE: This is not a question about which piece of code is better, but whether the two pieces actually produce the same behavior in all cases. I think the majority (and I) can agree that the former piece of code should be used.
Yes, those two are the same. foo() will always be called (assuming bar is true).
The two forms you give are equivalent. The C11 standard (draft n1570) states,
6.5.13 Logical AND operator
...
Semantics
3 The && operator shall yield 1 if both of its operands compare unequal to 0;
otherwise, it yields 0. The result has type int.
4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right
evaluation; if the second operand is evaluated, there is a sequence point between
the evaluations of the first and second operands. If the first operand compares
equal to 0, the second operand is not evaluated.
Similar language appeared in all C standards so far.
You should probably prefer using the comma operator here (return foo(), 0;) because:
It's shorter (one character versus two for the operator, and you can get away with removing the left space character when using a comma, for a total of two fewer characters).
It gives you more flexibility, as you can return non-scalar types (such as structs), and a wider range of integers than just 0 or 1.
It conveys the intent better: "Discard return value of foo() and return something else (0) instead".
Now if you do chance upon a compiler that deletes the call to foo(), then either the compiler managed to prove that foo() is a function with no visible side-effects, or more likely it has a serious bug and you should report it.
Why obfuscate your code in the latter?
Use the former.
Easier to read i.e. this is easier to understand
if(bar) {
foo();
return 0;
}
Or unless got a problem with job security
Consider:
#include "stdio.h"
int main()
{
int a=3, b=4, c=5;
printf("%d %d %d\n", (a, b, c));
}
And the result is:
5 2280760 2281472
What is the explanation?
You have caused an undefined behavior:
This - (a,b,c) is evaluated as the last parameter, e.g. c, so the first printed number is 5 (c = 5) the other two are uninitialized parameters.
It doesn't work. It produces undefined behavior.
You supplied three format specifiers to printf and provided only one variadic argument, since in C (a,b,c) is an expression that evaluates to the value of c (read about the comma operator).
Since the number of arguments does not match the number of format specifiers, the behavior is undefined.
There are only two arguments to your printf call: "%d %d %d" and the result of evaluating (a,b,c).
The result of (a,b,c) is just the last item in the list: c, which is 5. That's passed to printf, which displays 5 for the first %d.
Since there are no more arguments, the remaining %d's just display whatever garbage is sitting on the call stack, resulting in the strange values you see.
I think you missing about comma expression,comma expression contains two operands of any type separated by a comma and has left-to-right associativity. The left operand is fully evaluated, possibly producing side effects, and its value, if there is one, is discarded. The right operand is then evaluated. The type and value of the result of a comma expression are those of its right operand, after the usual unary conversions.
The result of a comma expression is not an lvalue.
so you getting the above result
As IBM states in their documentation:
The primary use of the comma operator is to produce side effects in
the following situations:
Calling a function
Entering or repeating
an iteration loop
Testing a condition
Other situations where a side effect is required but the result of the expression is not immediately needed
MByD said:
This - (a,b,c) is evaluated as the last parameter, e.g. c, so the first printed number is 5 (c = 5) the other two are uninitialized parameters.
But a and b are not uninitialized (try the code below):
int a=3,b=4,c=5;
printf("%d %d %d\n",a,(a,b,c),b);
due to the bracket, it is assumed as one parameter, and due to parsing from left to right (as user null pointer said) it found c to be its value.
The above code outputs 3 5 4.
Although I wouldn't have written it myself, what is the expected result of the following statement where A (guaranteed to zero or positive integer) is greater than 1?
return A || 1;
In many languages, I would expect A to be returned, unless the value of A is zero, in which case 1 would be.
I don't have my C book to hand, but I note that in reality, the value 1 always seems to be returned. Is this a result of compiler optimisation or given the potential ambiguity of the expression, is it that the return value is non-deterministic?
The standard says
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.
See section 6.5.14 of the standard.
The expected result is YES (or true)
|| operator returns true value if at least one of its operands is true (2nd operand in your code is obviously true)
This is straight C (no Objective-C involved). It will always return 1.
In C, the result of ||, &&, or ! is always 0 or 1, never any other non-zero value, regardless of the values of the operands. That means your A || 1 will always yield 1.
with C-based languages any nonzero value is true(represented by 1). And if your A is zero it will check the other comparisons if it's an OR comparison
Suffice to say, in your example, whatever the value of A is, will always return 1 even if you are using || 2. with 2 being nonzero, when performed with logical operator OR, will always return true(represented by 1)
I believe that the compiler will optimize and not even examine the value of A. Can someone confirm? I was under the impression that with A&&0, A||1, and A||0 (=A&&1), the compiler saves time by recognizing that the expression can be simplified to 0, 1, or A respectively.