tags:

views:

832

answers:

9

Hi

int fkt(int &i)
{
  return i++;
}

int main()
{
  int i = 5;
  printf("%d ", fkt(i));
  printf("%d ", fkt(i));
  printf("%d ", fkt(i));
}

prints '5 6 7 '. Say I want to print '5 7 9 ' like this, is it possible to do it in a similar way without a temporary variable in fkt()? (A temporary variable would marginally decrease efficiency, right?) I.e., something like

return i+=2 

or

return i, i+=2; 

which both first increases i and then return it, what is not what I need.

Thanks

EDIT: The main reason, I do it in a function and not outside is because fkt will be a function pointer. The original function will do something else with i. I just feel that using {int temp = i; i+=2; return temp;} does not seem as nice as {return i++;}.

I don't care about printf, this is just for illustration of the use of the result.

EDIT2: Wow, that appears to be more of a chat here than a traditional board :) Thanks for all the answers. My fkt is actually this. Depending on some condition, I will define get_it as either get_it_1, get_it_2, or get_it_4:

unsigned int (*get_it)(char*&);

unsigned int get_it_1(char* &s)
  {return *((unsigned char*) s++);}
unsigned int get_it_2(char* &s)
  {unsigned int tmp = *((unsigned short int*) s); s += 2; return tmp;}
unsigned int get_it_4(char* &s)
  {unsigned int tmp = *((unsigned int*) s); s += 4; return tmp;}

For get_it_1, it is so simple... I'll try to give more background in the future...

+28  A: 

"A temporary variable would marginally decrease efficiency, right?"

Wrong.

Have you measured it? Please be aware that ++ only has magical efficiency powers on a PDP-11. On most other processors it's just the same as +=1. Please measure the two to see what the actual differences actually are.

S.Lott
+1 for magical pdp-11 powers
Luther Blissett
There shouldn't be any difference, because of the compiler optimizations...
Quonux
On a PDP-11, compiler optimisations are performed by humans ;)
Artelius
OK, I'm intrigued - what magic does a PDP-11 wield that means i++ is faster than i+=1? Some sort of on-chip incrementer instruction similar to INX/INY on the 6502, that the compiler knows about and uses in preference to a standard ALU addition?
Jonners
@Artelius, does that mean the humans are the compilers?
Matt Joiner
The PDP11's architecture (and many that have come since) could dereference and increment or decrement a pointer in one instruction. Often, the increment/decrement is forced to be the data size being loaded/stored (e.g. 1 if loading/storing a byte, 2 if a 16-bit word, etc.) Different processors support different combinations of pre- and post-increment/decrement. I know of no architecture that directly favors post-increment for anything other than pointer dereferencing, though some highly-pipelined processors might benefit from post-increment in some cases.
supercat
@Matt Joiner: Not compilers, just optimizers. Using pre-increment and post-increment `++` is purely a performance optimization tweak for things like I/O drivers and kernel data structure updates and the like. If they were too slow.
S.Lott
On an old Z80 chip, add was slower than inc :)
Michael Dorgan
The 6502 INC instruction is slower than ADC (aside from ADC [$nn,X]). However, whereas INC operates directly on memory, ADC operates on the Accumulator - thus the fastest ADC 'Add +1 to Memory' is actually LDA $memory / CLC / ADC #1 / STA $memory - which is 10 cycles, compared to INC $memory, which is 5, 6 or 7 cycles depending on addressing mode.So for a 6502 compiler (hah!) the pre/postfix operator ++i / i++ would be slower than i+=1 if it tried to 'optimise' using the INC instruction. :)
Jonners
+18  A: 

(A temporary variable would marginally decrease efficiency, right?)

If that's the main reason you're asking, then you're worrying far too early. Don't second-guess your compiler until you have an actual performance problem.

If you want fkt to be able to add different amounts to i, then you need to pass a parameter. There is no material reason to prefer ++ over +=.

Cogwheel - Matthew Orlando
+1: "you're worrying far too early".
S.Lott
+1: "Don't second-guess your compiler". A good motto for life.
bgs264
+9  A: 

You could increment twice, then subtract, something like:

return (i += 2) - 2

Just answering the question, though, I don't think you should be scared of using a temporary variable.

orangeoctopus
Best answer for the actual question. I agree with you and the other answers that the temporary would be better.
caspin
thanks, very clever!
Frank
As far as efficiency goes, compiling with gcc 4.4.1 -O2 produces the exact same assembly as using a temporary.
indiv
+2  A: 

A "temporary variable" will very unlikely decrease performance, as i++ has to hold the old state internally to (i.e. it implicitly uses what you call a temprorary variable). However, the instruction that is needed to increase by two may be slower than the one used for ++.

You can try:

int fkt(int &i)
{
  ++ii;
  return i++;
}

You can compare this to:

int fkt(int &i)
{
  int t = i;
  i += 2;
  return t;
}

That said, I don't think you should be doing any such performance considerations prematurely.

inflagranti
+3  A: 

If you really need that speed, then check the assembly code the compiler outputs. If you do:

int t = i;
i+=2;
return t;

then the compiler may optimize it while inlining the function into something like:

printf("%d ", i);
i+=2;

Which is as good as it's gonna get.

EDIT: Now you say you're jumping to this function via a function pointer? Calling a function by a pointer is pretty slow compared to using a temporary variable. I'm not certain, but I think I remember the Intel docs saying it's somewhere around 20-30 cpu cycles on Core 2s and i7s, that is if your function code is all in cache. Since the compiler cannot inline your function when it is called by a pointer, the ++ will also create a temporary variable anyways.

Ramónster
+3  A: 

A temporary variable would marginally decrease efficiency, right?

Always take in account "premature optimization is the root of all evil". Spend time on other parts then try to optimize this away. += and ++ will probably result in the same thing. Your PC will manage ;)

PoweRoy
+3  A: 

Well, you could do

return i+=2, i-2;

That said, just follow this simple maxim:

Write code that is easy to understand.

Code that is easy for a human to understand is usually easy for the compiler to understand and hence the compiler can optimise it.

Writing crazy stuff in an effort to optimise your code often just confuses the compiler and makes it harder for the compiler to optimise your code.

I would recommend

int fkt(int &i)
{
    int orig = i;
    i += 2;
    return orig;
}
Artelius
The difference in the assembley for these two should be insignificant and the second one is much nicer to read.
Martin York
+1 for the simple maxim, "Write code that is easy to understand."
Thomas Matthews
+1  A: 

I think what you really want is a functor:

class Fkt
{
   int num;
public:
   Fkt(int i) :num(i-2) {}
   operator()() { num+=2; return num; }
}

int main() 
{ 
  Fkt fkt(5); 
  printf("%d ", fkt()); 
  printf("%d ", fkt()); 
  printf("%d ", fkt()); 
} 
James Curran
A: 

What about

int a = 0;
++++a;

Increments +2 without temporary variables.

EDIT: Oops, sorry: didn't notice you want to achieve 5,7,9. This requires temporary variables so prefix notation can't be used.

AkiRoss
`++++a;` is illegal. You cannot modify a variable twice between sequence points.
James Curran
Does it mean I shall get a compile error? Because I don't.Anyway, I don't see why is illegal to do ++(++i). It seems perfectly legal to me to increase a variable before increase it again.But yo got the exp, so I guess I'm wrong anyway. Waiting for clarification :)
AkiRoss
Ok, I think I got it: I thought that prefix increment defined a sequence point, but seems not. So, ++a + ++b is illegal, too? As I read that + operator doesn't define one either.
AkiRoss
Sorry, I meant ++a + ++a :) obviously the former wouldn't change the same variable twice.
AkiRoss
`++++a;` is illegal even *without* considering sequence points; `++` only applies to lvalues, and the result of `++a` is not an lvalue.
caf
Maybe I'm wrong and misread it, but in 5.3.2 [expr.pre.incr] it says "The operand of prefix ++ is modified by adding 1, or set to true if it is bool (this use is deprecated). The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a completely-defined object type. The value is the new value of the operand; it is an lvalue."While in postfix is says "the result is an rvalue".
AkiRoss