Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Can anyone tell me how does this code work?
int Calc(int *arr, int m)
int result;
for (result &= 0; m; (arr[--m] & (0x1 << 0x1F)) ? result += arr[m]: Void());
return result;
I can't understand for loop:/
Where did you find this code so I can hunt that person down and beat him with a copy of Schildt?
It's no surprise you don't understand the loop; it wasn't written to be understandable. The only place this kind of code is acceptable is the IOCCC, except it's not obfuscated enough for that competition.
Taking each bit in turn:
result &= 0;
is a really funky way of initializing result to 0; it's shorthand for result = result & 0, which performs a bitwise-AND of result against 0 (giving 0) and assigns the result back to result. It's also unsafe, since an uninitialized object may contain a trap representation. That should have been written as simply result = 0.
m;
just checks the current value of m; the loop will run until it is 0. The loop basically starts at the last element and works its way down to the first.
(arr[--m] & (0x1 << 0x1F)) ? result += arr[m]: Void()
Ugh. So, the first thing it does is take the value of the array at index m-1 and does a bitwise and against 0x1 << 0x1F (1 shifted left 31 postitions, or essentially 0x80000000); if the result of this operation is non-zero, then we add the value of that array element to result, otherwise we execute some incredibly inappropriately named function that hopefully returns a 01. Given that we're dealing with signed integers, and that on most platforms an int is 32 bits wide, this code is obviously adding up negative values in result.
A slightly saner way of writing that would be
result = 0;
while ( m ) // or m != 0, or m > 0, whatever you prefer
{
if ( arr[--m] < 0 )
result += arr[m];
}
1. The conditional operator ?: isn't meant to be used as a control structure like this. The syntax is expr1 ? expr2 : expr3. First, expr1 is evaluated and all side effects applied; if it results in a non-zero value, then the result of the expression is expr2; otherwise, the result is expr3.
Part 1
Firstrly result &= 0 is used for setting 0 to result variable using bitwise AND operation. Bitwise with 0 will ever return 0.
You can write it simply this way: result = 0
The better (much optimal) way of doing this is: result ^= result. (Bitwise XOR)
Part 2
This loop will iterate while m is greater (or less) than 0. Because m expression will return true if m != 0.
Much secure way of doing it is m > 0.
Also you can use this expression, which is not making programm much optimal, but it will be cleaner to another programmer to understand your code: !!m (casting m variable to bool), which is equal to m != 0;
Part 3
In this part ternary operator (logical_expression ? expression_1 : expression_2) is used.
If logical_expression is true, then expression_1 will be executed, expression_2 will be executed otherwise.
So in your code, if this expression (arr[--m] & (0x1 << 0x1F)) returns true then we add arr[m] to result variable. And do nothing in another case.
Also m variable is decremented in ternary logical expression (arr[--m]).
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm studying C in school and I had this question, and I'm having trouble solving it.
What does the following code do?
#define N (100)
int main(void)
{
unsigned short i = 0;
unsigned long arr[2*N + 1];
unsigned long a = 0;
for (i = 0 ; i < N ; ++i) {
a ^= arr[i];
}
printf("%lu", a);
return 0;
}
It would be really helpful if you could explain it to me!
Thanks!
It's usually a good idea to explain what you understand, so we don't have to treat you as though you know nothing. Important note: This code behaves erratically. I'll discuss that later.
The exclusive or operator (^) produces its result by applying the following pattern to the binary representation of the numbers in question:
Where both operands (sides of the operator) contain different bits, the result will contain a 1 bit. For example, if the left hand side contains a right-most bit of 0 and the right hand side contains a right-most bit of 1, then the result will contain a right-most bit of 1.
Where both operands (sides of the operator) contain the same bit, the result will contain a 0.
So as an example, the operands of 15 ^ 1 have the following binary notation:
1111 ^
0001
... and the result of this exclusive or operation will be:
1110
Converted back to decimal, that's 14. Xor it with 1 again and you'll end up back at 15 (which is the property the silly xor swap takes advantage of).
The array[index] operator obtains the element within array at the position indicated by index.
The ^= operator is a compound operator. It combines the exclusive or and assignment operators. a ^= arr[i]; is roughly equivalent to a = a ^ arr[i];. That means: Calculate the exclusive or of a and arr[i], and assign it back into a.
for (i = 0 ; i < N ; ++i) /*
* XXX: Insert statement or block of code
*/
This denotes a loop, which will start by assigning the value 0 to i, will repeatedly execute the statement or block of code while i is less than N (100), incrementing i each time.
In summary, this code produces the exclusive or of the first 100 elements of the array arr. This is a form of crude checksum algorithm; the idea is to take a group of values and reduce them to a single value so that you can perform some form of integrity check on them later on, perhaps after they've been trasmited via the internet or an unreliable filesystem.
However, this code invokes undefined behaviour because it uses unspecified values. In order to avoid erratic behaviour such as unpredictable values or segfaults (or worse yet, situations like the heartbleed OpenSSL vulnerability) you need to make sure you give your variables values before you try to use those values.
The following declaration would explicitly initialise the first element to 42, and implicitly initialise all of the others to 0:
unsigned long arr[2*N + 1] = { 42 };
It is important to realise that the initialisation part of the declaration = { ... } is necessary if you want any elements not explicitly initialised to be zeroed.
this function will print unpredictable value.
because of unsigned long arr[2*N + 1]; arr is not initialized and it will have random content based on data on you memory.
a ^= arr[i]; is equal to a = a^arr[i]; so it will do this for multiple times (because of loop) and then it will print it.
I am using ROBOTC to program my robot, and I was using some code built by someone else. In a function, I see the line:
int leftDir = (left>0)*2-1;
leftDir is initialized to an integer, so what does the > do? I am under the impression that is is a binary shift, but I'm not sure. Can someone explain this?
Thanks.
The > is the greater than operator. In C result of comparison is either 1 for true or 0 for false. In other words the code above is logically equivalent to (but more compact):
int leftDir;
if (left > 0) {
leftDir = 1;
} else {
leftDir = -1;
}
The previous answer is correct, but i believe he intended it as a bit shifting operator. This would make sense because he went on to multiply the value by a number, implying that he isn't treating it as a boolean. He was incorrect, though, about the roobtc bit shifting notation. If you want to bit shift a number in robotc, use the following syntax:
int foo = 0b00001111 >> 2; //bit shifts the bianary number 00001111 over by two bits, so foo will be set to the result 00000011
I was in a technical interview where the interviewer gave me a piece of code like this
int a=1;
a++;
...something..
...something.
if(a==25)
a=0;
he said me to rewrite this code without using switch,if else or ternary operator for the if condition. How it can be done?
It's quite simple actually:
a *= (a != 25);
This will multiply a by 0 if a is equal to 25, else it will multiply a by 1.
If you're also not allowed to test for equality then here is a fully arithmetic way:
unsigned int v = a - 25;
/* test for bits set and put result in lsb of v */
v |= v >> 16;
v |= v >> 8;
v |= v >> 4;
v |= v >> 2;
v |= v >> 1;
/* set a to a if lsb of v is 1, else set to 0 */
a *= v & 1;
a != 25 || (a = 0);
This does not use "switch,if else or ternary operator"
The question, as posed, gives undefined behaviour since you are using an uninitialised variable. Therefore you are free to write any code you like (so long as it compiles).
See C standard 6.3.2.1p2:
If the lvalue designates an object of automatic storage duration that
could have been declared with the register storage class (never had
its address taken), and that object is uninitialized (not declared
with an initializer and no assignment to it has been performed prior
to use), the behavior is undefined.
That, in my opinion, is the smart answer: although you would be wise to be graceful when answering a question in this way.
Remember that assignment is just an ordinary expression, and as such can be used as part of another expression. For example you could use the short-circuit logical and operator:
a == 25 && (a = 0);
You need to put parenthesis around the assignment because assignment has lower precedence than the && operator.
Another interesting answer could be
for ( ; a == 25 ; ) {
a = 0; break;
}
This does not use 'if-else', 'switch' or 'ternary operator'
If the context implied is a counting loop where a always repeats the cycle 0..24, then perhaps a mathematically more appealing solution would be
a = (a+1) % 25;
But this of course wouldn't work in a sitation where a can be anything, and it should only be reset in case of a==25, while something a==26 should be left alone.
The interviewers might like it though, if you search for a "semantic" solution like that, and can explain when to use this.
I think interviewer wanted you to use this line instead of if:
a %= 25;
Suppose we have an int and want to toggle it between 0 and 1 in a boolean fashion. I thought of the following possibilities:
int value = 0; // May as well be 1
value = value == 0 ? 1 : 0;
value = (value + 1) % 2;
value = !value; // I was curious if that would do...
The third one seems to work. Why? Who decides that !0 is 1?
Is something wrong with any of these?
Are there other possibilities? e.g. bitwise operators?
Which offers the best performance?
Would all that be identical with _Bool (or bool from stdbool.h)? If not, what are the differences?
EDIT: Many great answers with lots of valuable information, thanks! Unfortunately, I can only accept one.
value = !value; expresses what you want to do directly, and it does exactly what you want to do by definition.
Use that expression.
From C99 6.5.3.3/5 "Unary arithmetic operators":
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).
The third one seems to work. Why? Who decides that !0 is 1?
C Standard guarantees that !0 is 1.
Are there other possibilities? e.g. bitwise operators?
Yes, you can use the exclusive OR operator:
value ^= 1;
By the way I prefer this to value = !value; as relational and equality operators can result to branching and bitwise operators usually do not.
value = 1 - value; // toggle from 0 to 1 ... or 1 to 0
// when you know initial value is either 0 or 1
the language was designed that way.
Use the 3rd one, the others are right but unnecessarly complicated and therefore hiding the intent.
value = (value ^ 1) & 1;
They're all the same after optimisation.
_Bool would have the same results. The only thing different with _Bool is that values are coerced to be either 1 or 0. Meaning that bool x = 55; will have the value x == 1
EDIT: Corrected the formula in 3 because of my brainfart. I let the comments so that people can see my blooper.
value = !value seems the most reasonable one, but you can also use value = 1 - value or value ^= 1. But the last two would both break if value is not 0 or 1. The first one would still work.
There can be noticeable performance issues with the alternatives depending on the architecture:
!a might need in some architectures comparison and branching, which can be expensive depending on the pattern of 'a'
on some architectures there is conditional move (which is branchless), but
which may require still 3 instructions to complete (with dependencies)
1-a most likely needs two instructions in many architectures
counter example: ARM has reverse subtraction RSB %r0, %r0, #1
1^a can be implemented in many architecture with a single instruction
a=(a+1) % 2 will be most likely optimized to a=(a+1)&1, which requires 2 instructions
But anyway the first rule of optimization is that don't optimize a non working code.
To replace !a with a^1, one has to be 100% certain that it produces always the expected value.
Your expression value = value == 0 ? 1 : 0; will work exactly like value = !value;. You can use any of the two.
!0 is always 1 and also !(any non zero value) is 0
Use bitwise NOT operator
var = ~var;
I had this question after reading the Stack Overflow quesion Print an int in binary representation using C.
In a user's comment, they posted this for loop, which assigns either a 1 or a 0 to the bit position in order to convert from an int decimal to char * binary.
for(; bits--; u >>= 1)
str[bits] = u & 1 ? '1' : '0';
I understand why there doesn't need to be an initialized value. This is the syntax for a for loop that I've always known:
for ( variable initialization; condition; variable update )
I don't understand how 'bit--' can be an exit condition. Please help me understand how this code works (I tested it, and it is valid).
In C, a value of zero evaluates to "false" in a Boolean context. So when bits-- evaluates to 0, in the context of the loop it evaluates to "false" and terminates the loop.
If you say, for example:
int x = 1;
if (--x)
{
printf("True!\n");
}
else
{
printf("False!\n");
}
It will output "False", because --x evaluates to 0, which is "false" in a Boolean context.
All conditions basically boil down to checking whether something is 0 or not. 0 means false, everything else means true. So that loop will break when bits is 0.
You will sometimes see while or if conditions written
if (variable) // or while(variable)
That is just shorthand for
if (variable != 0) // or while (variable != 0)
So
for (; bits--; u >>= 1)
is short for
for (; bits-- != 0; u >>= 1)
bits-- is an assignment expression of type int (since it will return the value of b, which is int). To match the for loop syntax, it gets converted to a Boolean expression, which means it is true if bits != 0.
In fact, the condition is identical to bits!=0, but by using bits--, it changes the value of bits at the same time, making the code more compact. That's all.
As others said, in C, you can use integers as a condition - 0 or false, and anything else for true. (Actually, you almost always do it - even an expression like a<b is an int.)
So, the loop will end when bits-- will be 0.
When the -- operator comes after the variable, it decreases the variable, and gets the previous value of it. For example, if you have int a=3,b; b=a--;, then b will be 3, and a will be 2.
So, the loop will exit after that bits will been decreased from 0 to -1.
That means that, if in the beginning, bits==8 (for example), the loop will iterate 8 times, when in the first, bits will be 7 (because the condition had checked), and in the last, bits will be 0. It is a nice way to loop through an array (Since in C, an array of bits variables is being indexed from 0 to bits-1).