Hi there, sorry to bug you again, but I always learn useful stuff here -- again I'm writing a column -- and again I would appreciate the benefit of your feedback.
Question 1: Suppose we have a variable called Fred. As far as I'm aware, there are four ways we can increment this variable:
Fred = Fred +1;
Fred += 1;
Are you aware of any others (including any cunning tricks)?
Question 2: When it comes to the C operators, what are the most common misconceptions or errors in usage you've come across. For example, using:
Fred >> 1;
When you really mean to use:
Fred = Fred >> 1; or Fred >>= 1;
Thanks as always -- Max
It depends on definitions:
Fred -= -1;
Fred = increment(Fred);
not as different as your 4, but not the same.
I can't comment on frequency of confusion but one of the worst is thinking that:
(Fred >> 1) == (Fred / 2)
somtimes it will and sometimes it won't
Ooh -- I like the "Fred -= -1;"
Re the (Fred >> 1) == (Fred / 2) -- is the "sometimes it won't" tied to the way different compilers treat signed integers -- will it always work for unsigned integers?
Using Fred -= -1; is not as unusual as you might think.
The AVR Compiler for ATMEGA chips almost always adds numbers by subtracting their -ve equivalent. Probably other compilers do too.
Oooh - good question - smarter minds than me write compilers!
Here's an example:
First the C code:
And the same line compiled:
Yes it will, there is an article on Stackoverflow about using right shift instead of divide.
The best advice is don't, let: the compiler decide when that optimisation is OK.
Question 1: My suggestions (tested)
uint8_t fred = 40;
uint8_t i, o;
printf("Fred: %u\n", fred);
fred -= sizeof(fred)*255;
printf("Fred++: %u\n", fred);
// The hard way ...
printf("Fred++++: %u\n", fred);
You should enter the Obfuscated C Code Contest (https://www.ioccc.org/).
You have a really good chance to win!
I agree -- my eyes are still watering after reading TCFKAT's code
But this is a simple bit-wise addition with a ripple-carry loop, nothing magic. Using digraphs and trigraphs, special variable names and removing all unnecessary whitespaces makes it more obfuscated:
int main()<%unsigned _,__,___=41;printf("f:%u\n",___);(___&1)?(___&=??-1,__=1,_=1):(___??!=1,__=0);while(__&&_<sizeof(___)*8)(___&1<<_)?(___&=??-(1<<_),_++):(___??!=1<<_,__=0);printf("f++:%u\n",___);%>
If you are fired you should quickly change all code to this ... ;)
gcc -std=c11 -Wpedantic compiles without any warnings! ;)
Max, you asked for some cunning tricks to increment.
"If you are fired you should quickly change all code to this"
Afaik there are tools to do that. Or, are at least easy to write: removing all comments and whitespaces, rename all variables to cryptic random names, replace all by digraphs/trigraphs, etc.
But in times of revision control systems this is useless ...
@Max: sorry to go somewhat offtopic!
Hang on, you can say ++++ ?
Does that mean you could say:
But the prefix works different to the postfix -- so if I were to say:
Bert = --Fred++++;
I'd end up with Bert containing Fred + 2
However, () are at the highest precidence, so if I said
Bert = (--Fred++++);
Then I'd end up with Bert = Fred + 1 ... right?
The "++++" is only in the string, this is symbolic for two increments ... it is not a valid C syntax.
Ah -- my bad -- but then why doesn't the following work:
I guess the '--' operator is intended to be used in very simple operations and this is not the case.
The compiler complaints that 'Fred++' is not an lvalue, but it would, after evaluation. Even '--(Fred++)' does not work!
Perhaps more skilled people here can have a better answer.
Thanks for the explanation!
'Fred++' is an operation, hence, not an lvalue, even after executed.
It's starting to make sense :-)