Skip navigation

Whenever I code in C, one of my biggest annoyances is that there is no built-in function for determining an array’s size. So I either resort to hard-coding the maximum size the arrays my program will use (which is a waste of memory and is inflexible) or I allocate arrays dynamically (which is cumbersome).

When I mastered my bits a bit more, I realized that an array’s size can actually be determined by doing sizeof(array)/sizeof(array[0]). I then coded a function that will do just that for me. However, there are two problems with this:

  1. I’d have to define this function for every possible data type I’ll make an array of. AFAIK, C doesn’t have something like Java’s Object super-root class; and
  2. C is one hell of a liar. Among the things I (as a beginner and even as someone with moderate C experience) find very messy with C is that it is a pass-by-value language but it uses explicit pointers and so manages to act like a pass-by-reference language. Confusing, right?

Let’s a dwell a bit more on #2. Whenever you pass an array or a struct to some C function, say foo , that function can modify the contents of the array/struct for the whole program to see. It would seem to us that foo was given the whole array/struct upon function call. But no. C actually went behind your back1 and passed a pointer to the array/struct. That pointer is just an integer although C knows that it refers to some place in memory and uses that to modify the contents of your array/struct.

And boom. There goes the problem with doing

int size(int *array){
	return sizeof(array)/sizeof(array[1]);
}

as sizeof(array) will always return 4—the number of bytes in an integer (pointer).

I gave up my hopes on making C a bit more Java-ish for my taste. Until I (recently!) learned what macros are for.

Macros are the #define statements at the beginning of a C code listing, just after the #includes. I know that they can contain virtually almost every kind of C code but I’ve neglected that and up to now only used them to define constants. Assigning sizeof(array)/sizeof(array[0]) to a macro gives me just the thing I’m looking for.

So why would a lowly macro work where functions failed? It’s because of how macros are parsed. Whenever C encounters a macro, the bit of code assigned to that macro is, shall we say, copy-pasted directly into your code. So when we see

1
2
3
4
5
6
7
8
#include <stdio.h>
 
#define ARRAY_SIZE(array) ((sizeof(array) / sizeof(array[0])))
 
int main(){
	int foo[9] = {1,4,1,5,9,2,6,5,3};
	printf("%d\n", ARRAY_SIZE(foo));
}

C actually understands line 7 as

7
printf("%d\n", ((sizeof(foo) / sizeof(foo[0]))));

No parameter passing occurs, and hence no pointers. Everything is executed inline. While this may make parsing a bit longer, it surely is worth more than what it costs. And though it may not still be as nifty as Java (see what happens when you use that macro inside some function that requires an array as a parameter), it sure becomes less awkward with this.

Post Script. I orginally saw this trick here (CTRL+F to Chapter 17). Apparently, Linux has this macro pre-defined in linux/kernel.h . kernel.h includes fine in my machine but then it doesn’t seem to have the aforementioned macro. I opened my kernel.h and, indeed, it is not there. Weird.

  1. I just realized that C gurus will squirm at my choice of words. But hey, this is for non-gurus like me, alright? ;D []

Leave a Reply

Your email address will not be published. Required fields are marked *