LuminousMonkey

Throwaway variables in C

I'm re-reading "Refactoring" by Martin Fowler, which in turn was the result of me re-reading Steve Yegge's blog post (unfortunately I can't remember the post). One of the common things that programmers do, that may be a sacrifice of readability for optimisation, are temporary variables. As it turns out, this is an optimisation that seems like it doesn't have to be done.

Unfortunately I don't have any large project that I can use as an example, so I've had to create my own contrived test.

#include <stdio.h>

int square(int);

int main()
{
for (int i = 0; i < 5; i++)
{
printf("Result: %d\n", square(i));
}

printf("Called again: %d\n", square(3));
}

int square(int toBeSquared)
{
}


This code doesn't have any temporary variables, because I wanted to see what the compiler would do without them. The usual case for a temporary variable is something like the following:

  int tempVariable = someFunction(x);

for (int i = 0; i < tempVariable; i++)
{
printf("Blah: %d\n");
}

Of course this is done so you're not calling someFunction on every test of the loop. But, at least with optimisations turned on, you don't have to worry.

Anyway, I compiled my contrived example with GCC:

gcc -fverbose-asm -std=c99 -O3 blah.c -S


Checking the resulting code, we have:

main:
.LFB3:
.cfi_startproc
pushq %rbx  #
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
xorl  %ebx, %ebx  # i
.L2:
movl  %ebx, %esi  # i, D.2001
xorl  %eax, %eax  #
movl  $.LC0, %edi #, imull %ebx, %esi # i, D.2001 addl$1, %ebx  #, i
call  printf  #
cmpl  $5, %ebx #, i jne .L2 #, movl$9, %esi  #,
movl  \$.LC1, %edi #,
xorl  %eax, %eax  #
call  printf  #
xorl  %eax, %eax  #
popq  %rbx  #
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE3:
.size main, .-main
.section  .text.unlikely
.LCOLDE2:
.section  .text.startup
.LHOTE2:
.section  .text.unlikely
.LCOLDB3:
.text
.LHOTB3:
.p2align 4,,15
.globl  square
.type square, @function
square:
.LFB4:
.cfi_startproc
movl  %edi, %eax  # toBeSquared, D.2006
imull %edi, %eax  # toBeSquared, D.2006
ret
.cfi_endproc


Well, we have a function that gets made inline inside the for loop, and looking at my call to the function outside the loop, we can see it doesn't even bother, it just loads the value 9.

Now, this is a very simple function, and I would have to do more tests, but it would appear that the performance of certain refactorings, in particular ones involving replacing math and Boolean operations should not be a concern.

Write it as clear as possible, even to the extent of using a function just so you can give Boolean conditions a better name, and don't bother to use temp variables to cache results to avoid what you might think will be a function call. The compiler probably does it anyway.

Drinking the Emacs firehose.

In my wanderings of the Internet, I can't really remember what I was searching for, something Emacs related, I came across an interesting blog. Living an awesome life, is the blog of Sacha Chua a software developer who is very heavily into both blogging (her blog has regular posts spanning back to 2001), and organising her life using Emacs. Wow, really, wow. Her productivity really puts me to shame, so, I've been inspired.

I've decided that my current hobbyist usage of Emacs, and general organisation skills are simply not up to par and I should really make the effort to get better organised. Part of that is to actually blog regularly, and switch to using Emacs for everything I can.

The first stage being to switch to using Gnus to read my e-mails. Which I've done. It's still a little rough, but I can read and reply to e-mails (and it seems to be working). This also has a bonus, I can link to my e-mails from org-mode! Next thing I want to do is get my org-mode workflow a bit smoother, and then try to get any blogging as friction-less as possible.