eggfriedrice.com

When is long not long?

February 4th, 2007

When it’s exactly the same length as something shorter!

For my Higher Computing C Programming assessment I’ve had to write a simple program, part of which calculates the file size of a video by multiplying the height, width, colour depth, number of frames per second and length. Simple? I thought so.

I’ve done a bit of C programming, but mostly for 8 bit microcontrollers, I’m used to thinking in terms of unsigned chars and this is my downfall here.

Using one of the example tests for the program gives a sum like this 270 * 340 * 16 * 25 * 189 = 6,940,080,000. That’s too big for an int. Luckily C has datatypes for bigger numbers, like “long” and “long long” (for even longer things). Great! So all I need to do is swap to longs or long longs and then it’ll work! Except this is stepping into a bit of a minefield.

It turns out that a long is exactly the same length as an int on 32 bit computers (like most of mine). On my Linux and Windows boxes an int is 32 bits long. So, a long long it is then! That’s 64 bits everywhere I’ve looked. Only as it’s quite uncommon I found it tricky to work out what to use at the format specifier. This is mostly because long longs seem to be a GCC addition to the C language, not part of the spec. That’s fine because I’m using GCC on Linux to develop this program and at college we’re using Bloodshed Dev-C++ under Windows XP.

Dev-C++ is a nice, lightweight and open source IDE for C and C++. I was quite impressed with Telford College for choosing something open source for their Windows boxes (I’m adding more OS software by running Firefox at Telford using the portableapps version from the student network share).

Anyway, back to the problem. %lld is the GCC printf specifier for a long long, nice and easy to remember, ll == long long. And luckily Dev-C++ uses the MinGW version of GCC so I can port my code straight over. Ha! No such luck. It turns out (I discovered after some really handy exchanges on the Edlug mailing list) that the MinGW GCC implementation of printf is actually made to use the Microsoft long long print specifier with is %I64d. Catchy. Unless you use %I64 you experience some sort of weird miscounting thing and printf prints out garbage. This page explains it.

So after all the faffing around and general irritation of this half hour job taking three days I finally have it working. Along the way I discovered that for a language that’s been around for a million years C isn’t all that well defined. Also, I found that the datatypes vary. I knew this was the case anyway but I didn’t realise how weirdly they vary.

I’ve complied and run this code on a few different computers here:

#include

int main(){
printf(" TYPE BYTES BITS\n");
printf(" char: %d %3d\n", sizeof(char), sizeof(char)*8);
printf(" short: %d %3d\n", sizeof(short), sizeof(short)*8);
printf(" int: %d %3d\n", sizeof(int), sizeof(int)*8);
printf(" long: %d %3d\n", sizeof(long), sizeof(long)*8);
printf("long long: %d %3d\n", sizeof(long long), sizeof(long long)*8);

return 0;
}

I expected the length of an int to be 32 bits on a 32 bit system and 64 bits on a 64bit system. Strangely it seems to be 32 bits everywhere but the long is 32 bits on a 32 bit system and 64 bits on a 64 bit system. That’s enough, I’m past caring, it’s all too weird! I’m almost beginning to wish they’d chosen to teach Java this year and that’s a really bad sign!

Apologies to the non-geeks who might read this entry but well done for getting this far! Apologies to the geeks who read this entry, but well done for getting this far without posting a comment pointing out a cockup or inaccuracy, you can post it now!