Hacker News new | ask | show | jobs
by kazinator 1119 days ago
The following error prone: it can be mistakenly applied to a pointer:

#define LEN(NAME) (sizeof NAME / sizeof(NAME)[0])

I think gcc has a warning for this pattern now: when the size of a pointer is divided by the size of its referent type.

More importantly, it has an odd extra level of indirection. The traditional definition is:

#define LEN(ARRAY) (sizeof ARRAY / sizeof (ARRAY)[0])

This means that to use LEN on an array, we have to take the address:

   char *array[5];
   LEN(&array);  // -> 5
If we use

   LEN(array);
which is an easy mistake, we get:

    sizeof *array / sizeof (*array)[0]
which is

    sizeof (char *) / sizeof (char)
which is

    sizeof (char *)
which is likely 4 or 8.

I do see that LEN is supposed to be (only) used in conjunction with ARR:

    #define ARR(TYPE, NAME, COUNT) TYPE(*NAME)[COUNT]
but that isn't enforced. An idea would be to add some "secret" prefix or suffix to NAME like blah_ ## NAME, so that name cannot be referenced without going through the macros; i.e. if we define ARR(int, foo, 42) then there is no declared identifier foo; it actually declares blah_foo, and LEN(foo) knows about that, also adding the prefix. Thus mistakenly using LEN(foo) on something not declared with ARR will likely be a reference to an undeclared identifier.
1 comments

It's so funny, but i actually had this in 0.0.1 for exact same reason. I removed it in 0.0.2 today after complains that it complicates things and a bit confusing. It made harder to pass VLAs to functions. Maybe if i find a better way i will return name mangling again, but for now being able to pass arrays to functions and maintain same flexibility is more important imo