Forums

Five different ways of incrementing a variable in C?

Started by MaxMaxfield 1 month ago22 replieslatest reply 1 month ago113 views

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;

Fred++;

++Fred;

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

[ - ]
Reply by MichaelKellettMarch 16, 2021

It depends on definitions:

how about:

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


MK

[ - ]
Reply by MaxMaxfieldMarch 16, 2021

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?

[ - ]
Reply by SpiderKennyMarch 16, 2021

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.



[ - ]
Reply by MaxMaxfieldMarch 16, 2021
"The AVR Compiler for ATMEGA chips almost always adds numbers by subtracting their -ve equivalent."


Why?

[ - ]
Reply by SpiderKennyMarch 16, 2021

Oooh - good question - smarter minds than me write compilers!

Here's an example:

First the C code:

screenshot 2021-03-16 143829_40014.png

And the same line compiled:

screenshot 2021-03-16 143610_49407.png

[ - ]
Reply by MichaelKellettMarch 16, 2021

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.


MK

[ - ]
Reply by tcfkatMarch 16, 2021

Question 1: My suggestions (tested)

#include <stdio.h>
#include <stdint.h>

void main(void){
  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 ...
  (fred&1)?(fred&=~1,o=1,i=1):(fred|=1,o=0);
  while(o&&i<sizeof(fred)*8)(fred&1<<i)?(fred&=~(1<<i),i++):(fred|=1<<i,o=0);
  printf("Fred++++: %u\n", fred);
}

[ - ]
Reply by DilbertoMarch 16, 2021

Hi, tcfkat!

You should enter the Obfuscated C Code Contest (https://www.ioccc.org/).

You have a really good chance to win!

:-)

[ - ]
Reply by MaxMaxfieldMarch 16, 2021

I agree -- my eyes are still watering after reading TCFKAT's code

[ - ]
Reply by tcfkatMarch 16, 2021

Oh, thanks!

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:

??=include<stdio.h>
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.

[ - ]
Reply by MaxMaxfieldMarch 16, 2021
"Max, you asked for some cunning tricks to increment."I was hoping I'd be able to understand them LOL
[ - ]
Reply by DilbertoMarch 17, 2021


"If you are fired you should quickly change all code to this"

Interesting idea!!!


:-)

[ - ]
Reply by DilbertoMarch 17, 2021

:-)

[ - ]
Reply by tcfkatMarch 17, 2021

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!

[ - ]
Reply by MaxMaxfieldMarch 16, 2021

Hang on, you can say ++++ ?

Does that mean you could say:

--Fred++++;

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?

[ - ]
Reply by tcfkatMarch 16, 2021

The "++++" is only in the string, this is symbolic for two increments ... it is not a valid C syntax.

[ - ]
Reply by MaxMaxfieldMarch 16, 2021

Ah -- my bad -- but then why doesn't the following work:

--Fred++;

[ - ]
Reply by DilbertoMarch 16, 2021

Hi, MaxMaxfield!

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.

Cheers!



[ - ]
Reply by waydanMarch 16, 2021
The prefix or postfix increment/decrement operator requires an lvalue and returns the value pre-modification. Since an rvalue (temporary) is returned, you can’t call a second increment/decrement.


https://en.cppreference.com/w/c/language/operator_incdec

[ - ]
Reply by DilbertoMarch 17, 2021

Thanks for the explanation!


[ - ]
Reply by DilbertoMarch 16, 2021

Other thinking:

'Fred++' is an operation, hence, not an lvalue, even after executed.

[ - ]
Reply by MaxMaxfieldMarch 17, 2021

It's starting to make sense :-)