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 14 days ago.
Improve this question
I would like to clear, and test a particular bit in single statement, for instance to clear bit 27 and test the same bit, and wanted to return the status for same:
{
status = number & BIT(27);
if (status)
number & ~BIT(27);
return number & BIT(27);
}
Is there way to do it using Ternary operator ?
The code fragment does not modify number so it will return the bit value but not clear it. You probably meant this instead:
#define BIT(n) (1U << (n)) // assuming this definition for BIT or similar
{
status = number & BIT(27);
if (status)
number &= ~BIT(27);
return status;
}
You can indeed achieve this in a single expression using the ternary operator and a comma expression:
return (number & BIT(27)) ? (number &= ~BIT(27), BIT(27)) : 0;
or this alternative:
return (number & BIT(27)) ? (number ^= BIT(27), BIT(27)) : 0;
There is a sequence point between the evaluation of the test expression and the evaluation of the second or third expression, so it is OK to modify number this way as a side effect.
This approach may allow you to encapsulate the test and clear trick inside an expression macro, but be aware that this macro would evaluate number twice. You might consider an inline function taking the address of number:
static inline int test_and_clear27(int *number) {
if (*number & BIT(27)) {
*number &= ~BIT(27);
return BIT(27);
} else {
return 0;
}
}
Or without branches:
static inline int test_and_clear27(int *number) {
int status = *number & BIT(27);
*number &= ~BIT(27);
return status;
}
These methods are not thread safe: it cannot be used to implement semaphores as the test and clear operations are separate and do not happen atomically.
Your current code does not do what your description claims. Instead, it is equivalent to
return number & BIT(27);
— A nice, concise, single statement.
However, assuming that you actually do wanted to clear bit 27, the following code does that (the if in your code is unnecessary):
status = number & BIT(27);
number &= ~ BIT(27);
return status;
There’s really no good reason to rewrite this as a single statement (except by encapsulating it inside a function1). But, just for argument’s sake, it is possible. chqrlie has already posted an answer, but if you only use status as a boolean flag you can shorten the code and remove the conditional operator:
return (number & BIT(27)) && (number &= ~ BIT(27), 1);
Is this better than the three-statement solution? Absolutely not! On the contrary: it introduces a branch into the logic which, if anything, makes this code slower.
1 And as per Ian Abbott’s comment the Linux kernel provides just such a function: test_and_clear_bit(), but be careful since it requires to have a variable of unsigned long type and any casting to it is a very bad idea.
Related
I saw this code:
if (cond) {
perror("an error occurred"), exit(1);
}
Why would you do that? Why not just:
if (cond) {
perror("an error occurred");
exit(1);
}
In your example it serves no reason at all. It is on occasion useful when written as
if(cond)
perror("an error occured"), exit(1) ;
-- then you don't need curly braces. But it's an invitation to disaster.
The comma operator is to put two or more expressions in a position where the reference only allows one. In your case, there is no need to use it; in other cases, such as in a while loop, it may be useful:
while (a = b, c < d)
...
where the actual "evaluation" of the while loop is governed solely on the last expression.
Legitimate cases of the comma operator are rare, but they do exist. One example is when you want to have something happen inside of a conditional evaluation. For instance:
std::wstring example;
auto it = example.begin();
while (it = std::find(it, example.end(), L'\\'), it != example.end())
{
// Do something to each backslash in `example`
}
It can also be used in places where you can only place a single expression, but want two things to happen. For instance, the following loop increments x and decrements y in the for loop's third component:
int x = 0;
int y = some_number;
for(; x < y; ++x, --y)
{
// Do something which uses a converging x and y
}
Don't go looking for uses of it, but if it is appropriate, don't be afraid to use it, and don't be thrown for a loop if you see someone else using it. If you have two things which have no reason not to be separate statements, make them separate statements instead of using the comma operator.
The main use of the comma operator is obfuscation; it permits doing two
things where the reader only expects one. One of the most frequent
uses—adding side effects to a condition, falls under this
category. There are a few cases which might be considered valid,
however:
The one which was used to present it in K&R: incrementing two
variables in a for loop. In modern code, this might occur in a
function like std::transform, or std::copy, where an output iterator
is incremented symultaneously with the input iterator. (More often, of
course, these functions will contain a while loop, with the
incrementations in separate statements at the end of the loop. In such
cases, there's no point in using a comma rather than two statements.)
Another case which comes to mind is data validation of input parameters
in an initializer list:
MyClass::MyClass( T const& param )
: member( (validate( param ), param) )
{
}
(This assumes that validate( param ) will throw an exception if
something is wrong.) This use isn't particularly attractive, especially
as it needs the extra parentheses, but there aren't many alternatives.
Finally, I've sometimes seen the convention:
ScopedLock( myMutex ), protectedFunction();
, which avoids having to invent a name for the ScopedLock. To tell
the truth, I don't like it, but I have seen it used, and the alternative
of adding extra braces to ensure that the ScopedLock is immediately
destructed isn't very pretty either.
This can be better understood by taking some examples:
First:
Consider an expression:
x = ++j;
But for time being, if we need to assign a temporarily debug value, then we can write.
x = DEBUG_VALUE, ++j;
Second:
Comma , operators are frequently used in for() -loop e.g.:
for(i = 0, j = 10; i < N; j--, i++)
// ^ ^ here we can't use ;
Third:
One more example(actually one may find doing this interesting):
if (x = 16 / 4), if remainder is zero then print x = x - 1;
if (x = 16 / 5), if remainder is zero then print x = x + 1;
It can also be done in a single step;
if(x = n / d, n % d) // == x = n / d; if(n % d)
printf("Remainder not zero, x + 1 = %d", (x + 1));
else
printf("Remainder is zero, x - 1 = %d", (x - 1));
PS: It may also be interesting to know that sometimes it is disastrous to use , operator. For example in the question Strtok usage, code not working, by mistake, OP forgot to write name of the function and instead of writing tokens = strtok(NULL, ",'");, he wrote tokens = (NULL, ",'"); and he was not getting compilation error --but its a valid expression that tokens = ",'"; caused an infinite loop in his program.
The comma operator allows grouping expression where one is expected.
For example it can be useful in some case :
// In a loop
while ( a--, a < d ) ...
But in you case there is no reason to use it. It will be confusing... that's it...
In your case, it is just to avoid curly braces :
if(cond)
perror("an error occurred"), exit(1);
// =>
if (cond)
{
perror("an error occurred");
exit(1);
}
A link to a comma operator documentation.
There appear to be few practical uses of operator,().
Bjarne Stroustrup, The Design and Evolution of C++
Most of the oft usage of comma can be found out in the wikipedia article Comma_operator#Uses.
One interesting usage I have found out when using the boost::assign, where it had judiciously overloaded the operator to make it behave as a comma separated list of values which can be pushed to the end of a vector object
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace std;
using namespace boost::assign; // bring 'operator+=()' into scope
{
vector<int> values;
values += 1,2,3,4,5,6,7,8,9; // insert values at the end of the container
}
Unfortunately, the above usage which was popular for prototyping would now look archaic once compilers start supporting Uniform Initialization
So that leaves us back to
There appear to be few practical uses of operator,().
Bjarne Stroustrup, The Design and Evolution of C++
In your case, the comma operator is useless since it could have been used to avoid curly braces, but it's not the case since the writer has already put them. Therefore it's useless and may be confusing.
It could be useful for the itinerary operator if you want to execute two or more instructions when the condition is true or false. but keep in mind that the return value will be the most right expression due to the comma operator left to right evalutaion rule (I mean inside the parentheses)
For instance:
a<b?(x=5,b=6,d=i):exit(1);
The boost::assign overloads the comma operator heavily to achieve this kind of syntax:
vector<int> v;
v += 1,2,3,4,5,6,7,8,9;
I am new to SO - I have a question which I was asked in interview and which for life of me I am not able to wrap my head around. I can solve it with while/for loop but interviewer specifically asked not to use them I even discussed with few friends of mine but unable to solve it. If someone can provide pointers.
Question is:
for given array
s[] = {5,1,0,4,2,3}
length of array is not given.
If length of array is 5 content
is guaranteed to be between 0 to 5.
There is no repetition of
numbers.
Sample example length(s, 3)
- a[3] = 4 , a[4] = 2, a[2] = 0, a[0] = 5, a[5] =3 returns length of 4 .
For given condition write subroutine int length (s, 3) - to find the number of steps it takes to find given value -
Additional conditions
You cannot use any loop statements like for, while and so on -
You cannot use any global or static variables.
You cannot call other routines inside this routine
You cannot modify given function parameters - it stays length (s, n) only
You cannot change original array too
Alternative solution that does not modify the array at all, but hides an extra parameter inside top 16 bits of x:
int length(int *s, int x){
int start = (x >> 16) - 1;
if (start < 0)
start = x;
if (s[x] == start)
return 0;
return 1 + length(s, ((start + 1) << 16) + s[x]);
}
This will fail if there are too many elements in the array, but I suspect any other recursive solution is likely to hit a stack overflow by that point in any case.
I think I found the answer eventually no I didnt crack it but found it online :) .. Here is the solution
int length(int * s, int x){
if(s[x] < 0){
return -1;
}
else{
s[x] = -s[x];
int len = length(s, -s[x]);
s[x] = -s[x];
return len + 1;
}
}
i don't think it contradicts with any of your conditions. i just didn't use the array as a parameter (that isn't a problem actually, you can modify it yourself)
int s[] = {5,1,0,4,2,3};
bool col[100]; ///to check cycle
int rec(int n)
{
if(col[n])return 0;
col[n]=true;
int sum=0;
sum = 1+rec(s[n]);
return sum;
}
The interviewer is probing your understanding of algorithms and programming paradigms, trying to understand your training, background, and depth. The interviewer has a challenging task; identifying capable developers with minimal evidence. Thus the interviewer presents a constructed problem that (they hope) elicits the desired knowledge (does candidate X know how to solve problem Y, or understand concept Z) perhaps because the interviewer believes the desired answer indicates the candidate knows the expected body of knowledge.
Modern languages provide several repetition structures (commands, statements), some which pre-test (check condition before entering statement-block), and some which post-test (check condition after performing statement block at least once). Here are examples,
Pre-test
while(condition) statement-block
for(initializer;condition;step) statement-block
Post-test
do statement-block while(condition)
repeat statement-block until(condition)
do statement-block until(condition)
These can all be written as conditional (choice) structures with branching (goto),
Pre-test
label:
if(condition)
statement-block;
goto label;
else
nil;
endif
Post-test
label:
statement-block;
if(condition)
goto label;
endif
You can also use recursion, where you call the same function as long as condition holds (or until condition met, depending upon positive or negative logic),
Pre-test
function recurse(args)
if(condition)
statement-block
recurse(revised args);
endif
return
end #function
Post-test
function recurse(args)
statement-block
if(condition)
recurse(revised args);
endif
return;
end
You would learn about recursion in an algorithms, or perhaps a computability course. You would learn about conditional branching in a compiler, high performance computing, or systems class. Your compiler course might examine techniques for detecting 'tail-recursion', and how to rewrite the function call into a loop.
Here is the problem, restated,
given array, s[] = {5,1,0,4,2,3}
array length unknown
content between [0 .. length], not repeated, no duplicates
write subroutine which provides the number of steps to find given value
That is,
int length( array s, int member ) --> position
Examine the conditions (constraints) on the problem,
Array length unknown - Solution must work for variable range of inputs
Cannot use loop statements (for, while, etc) - This suggests either the interviewer wants conditional branch or recursion.
Cannot use global or static variables - Does this suggest interviewer wants a recursive/functional-programming solution? Conditional-branch also provides this.
Cannot call other routines inside this routine - Does interviewer mean functions other than same function, or call any function (what does interviewer mean by 'other').
Cannot modify function parameters, stays length(s,n) - Declaring local (stack) variables is allowed. This could mean pass by value, make a local copy, etc. But not destructive modifications.
Cannot change original array - Definitely no destructive modifications. Possible 'hint' (ok to make local copy?), or further indication that you should use conditional-branch?
Here are two solutions, and a test driver (note, I have named them lengthi, iterative, and lengthr, recursive).
#include <stdio.h>
/* conditional branch */
int lengthi( int s[], int member )
{
int position=0;
AGAIN:
if( s[position] == member ) return(position);
++position;
goto AGAIN;
return(-1);
}
/* recursive */
int lengthr( int s[], int member )
{
if( s[0] == member ) return(0);
return( 1+length(s+1,member) );
}
int
main(int argc,char* argv[])
{
int s1[] = {0,1,2,3,4,5,6,7,8,9};
int s2[] = {1,2,3,4,9,8,7,6,0,5};
int s3[] = {2,4,6,8,0,1,3,5,7,9};
printf("%d at %d\n",3,lengthr(s1,3));
printf("%d at %d\n",3,lengthr(s2,3));
printf("%d at %d\n",3,lengthr(s3,3));
printf("%d at %d\n",3,lengthi(s1,3));
printf("%d at %d\n",3,lengthi(s2,3));
printf("%d at %d\n",3,lengthi(s3,3));
}
Since we are supposed to find the number of steps (iterations, function calls), that is asking for the ordinal position in the list, not the C index (zero based) position.
This is an interview question, and not a programming problem (per se), so probably better suited for the Programmers.stackexchange site. I might give the interviewer an entertaining answer, or their desired answer.
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
#include <stdio.h>
#include <time.h>
unsigned int decrement(unsigned int value);
main()
{
clock_t start, end;
double cpu_time_used;
register unsigned int value;
value = 4294967;
start = clock();
decrement(value);
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("cpu_time_used %lf\n",cpu_time_used);
}
unsigned int decrement(register unsigned int value)
{
int i;
for(;value;value--)
{
printf("loop value %u\n",value);
}
return 0;
}
I have tried to decrement a large integer value with less execution time, to achieve that i am declaring a variable with register keyword like register unsigned int value from this i have not received any optimization results while run this program with/without using this register keyword. please correct me if i am wrong. and please share if we have any other method to decrement a larger number with minimum execution time.
program mentioned here is just for example with register keyword(one of the optimization method to reduce execution time) main agenda of this question is how to decrement a larger number with minimum execution time.
Without the understanding of the logic telling me the decrement(x) should be always zero, there is another problem:
value = value--; is invoking an undefined behaviour, as value-- is a post decrement operation having side effects. You want either value--; or value -=1. But not both.
When you're calling the decrement function, value is being passed in by value. This means that the value you're modifying in the decrement function isn't the one with the register keyword associated with it. You would would need to the decrementing in the same function that the register variable is define.
Even then, I question whether this is something you really need to do. Seems like a classic case of premature optimization to me.
register is commonly ignored by compilers... Anyway if something should be qualified register it is the variable value of the decrement function not the value of main. If you want to accelerate, why inserting an if inside the for loop? You may rewrite your code as :
unsigned int decrement(register unsigned int value)
{
for(;value;value--)
{
printf("loop value %u\n",value);
}
return 0;
}
Write slightly better code and let the compiler optimize...
I would modify the decrement funtion like this:
unsigned int decrement(unsigned int value)
{
for(value; value > 0; value--)
{
printf("loop value %u\n",value);
}
return value;
}
You dont need to say i >= 0 when you need that i is only > 0(see the if with the break when i == 0 ), you don't even need "i" just do the operation with the variable value, since that's what you want to return( That's what I understand from your code) Sorry for my bad English!
Sorry for my formatting as I am new here.
Please change value = value-- to just --value
Unless you are using it in a definite way/statement, post-increment operator is usually slower than pre-increment operator. Same goes for decrement as well.
Also, you do not need to do an explicit check for i>=0
Try this:
unsigned int decrement(register unsigned int value)
{
while(value>=0)
printf("loop value %u\n",value--);
return 0;
}
I have to write a function that calculates the floor of log base 16 of an unsigned int passed in. There are restrictions as to what operators and what constants we are allowed to use, and we can only use specifically for loops.
For clarity, we cannot use any conditional statements(if, else, switch ... ). The function prototype is:
int floor_log16(unsigned int x);
Allowed operators: ++ -- = & | ~ ^ << ! >>
Allowed constants: 1 2 3 4 8 16
I wrote a version of the program as follows:
int floor_log16(unsigned int x) {
int index=1;
int count=(1!=1);
count--;
for(; index<=x; index<<=4) {
count++;
}
return count;
}
which seems to work as desired. However, I realized that based on the later functions and description of the needed functionality we have to write, I noticed that under "allowed operators" sometimes > and < were listed.
I deduce this implies that since for the floor_log16 function listed above, we weren't explicitly told to use > or <, I can only assume that the solution posted above will not be accepted.
This leaves me rather confused because I don't understand how you can possibly have a for loop without a boolean check?
Isn't the whole idea of a loop to iterate while a condition is met?
Well, first of all, for-loop without the boolean check is perfectly fine. For example,
for (;;)
is a common way of writing
while (true)
Second, having a for-loop with other parts but without boolean check is still useful as you can exit it with return or break.
And the last thing. There are tons of ways of getting a boolean without using < and >. For example, you can simply use i to check that i != 0 and so on.
For example if you want to check that a < b you can check for (a - b) < 0 instead. Implementing addition (and hence subtraction) with bitwise operators is a well known interview question (you should really try to do this yourself, it's fun), and checking that your int is negative is as easy as looking at its most significant bit.
I don't like to spoil your task but consider about for condition like 'comparison to 0'. This doesn't require any explicit operator. One of possible way to get it is something like this:
// This cycle will end as soon as index is 0.
for (;index; index = (index >> 4))
{
// ...
}
If you XOR any unsigned with itself, it becomes 0. So int count=(1!=1); could be changed to int count = 1 ^ 1.
As for the loop condition, Roman's idea of comparison to 0 seems like the most natural way to go.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Double Negation in C++ code
While reading one code I read:
flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
I am not getting what does !! mean here .
what does this sentence do?
EDIT:
I got it its a double-negative. trick to convert non-bool data to bool
But what is the need of that? Here flush is bool then if you assign any non zero item to bool it will treat as 1 and zero item as 0 so whats benefit of doing this?
It's a double-negative. It's a way of converting an otherwise-non-bool expression (such as flags & GST_SEEK_FLAG_FLUSH) to a bool. I personally prefer:
flush = (flags & GST_SEEK_FLAG_FLUSH) != 0;
If flush is boolean variable, and you force some non-boolean value to it, some compiler will generate a warning forcing value to bool 'true' or 'false'. So it's safer to use double negation.
Some compilers (like Visual Studio) will warn when coercing a non-boolean type to an int, for example:
#include <stdio.h>
int main(void) {
int x = 10;
bool y = x; // warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
return 0;
}
The double-negation trick is one way of converting to bool and preventing this warning, however I would lean towards the != 0 check Jim Buck recommended for clarity.
Just wanted to add a little example for you that might clear things.
main()
{
int i=10;
printf("%d",!!i);
}
Output is 1