Not the usual assert() macro then?! Do you really need a
number? What do you do with it? What's wrong with __FILE__?
Well, if you're braindead enough to put in the dummy function...
I would create a separate header file
filenums.h:
enum {
FILEA=1,
FILEB=2,
FILEC=3};
In file filea.c:
#include "filenums.h"
#define F_NUM FILEA
Keep the entries in filenums.h in numeric order, which
allows you to easily verify uniqueness manually. You
could, of course, omit the explicit enum assignment, but
then the numeric value isn't obvious. You could also
write a utility to verify uniqueness and run it as part
of the build process.
Built in uniqueness...
/* begin header */
#define FILE_NAMES(M,_) \
M( FILE_A, "FileA.c" ) _ \
M( FILE_B, "FileB.c" ) _ \
M( FILE_C, "FileC.c" ) _ \
M( FILE_D, "FileD.c" )
#define COMMA ,
#define SEMI_COLON ;
#define AS_ENUM(a,b) a
enum { FILE_NULL=0, FILE_NAMES(AS_ENUM, COMMA) };
/* end header */
#include <stdio.h>
/* include above header in required files */
#define AS_PRINTF(a,b) printf("%s,%d,\"%s\"\n", #a, a, b)
int main(void)
{
FILE_NAMES(AS_PRINTF, SEMI_COLON);
return 0;
}
Assigned values validator...
/* begin header */
#define FILE_NAMES(M,_) \
M( FILE_A, 1, "FileA.c" ) _ \
M( FILE_B, 2, "FileB.c" ) _ \
M( FILE_C, 3, "FileC.c" ) _ \
M( FILE_D, 2, "FileD.c" )
#define COMMA ,
#define SEMI_COLON ;
#define AS_ENUM(a,b,c) a = b
enum { FILE_NULL=0, FILE_NAMES(AS_ENUM, COMMA) };
/* end header */
#include <stdio.h>
/* include above header in required files */
#define AS_ARRAY(a,b,c) { #a, a }
struct {
const char *enum_name;
int value;
} array[] = { FILE_NAMES(AS_ARRAY, COMMA) };
#define countof(x) (sizeof(x) / sizeof*(x))
int main(void)
{
int okay = 1;
size_t i, j;
for (i = 0; i < countof(array) - 1; i++)
for (j = i + 1; j < countof(array); j++)
if (array
.value == array[j].value)
{
printf("%s and %s both have value %d\n",
array.enum_name,
array[j].enum_name,
array.value);
okay = 0;
}
if (okay) puts("okay!");
return 0;
}