By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,864 Members | 1,293 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,864 IT Pros & Developers. It's quick & easy.

Globally unique enums or macro values?

P: n/a
Hi
Does anyone know if there is a way to define what is effectively a
single globally visible, enumerated list whilst actually defining the
entries across several different modules?
or somehow do a similar thing with macros.

Details:
I have a c project to fit into a small microprocessor and need to save
some ram. I have a significant number of flags all over the place that
currently use whole byte storage. I thought if I had a way to define a
list of numerically sequential flag names, I could assign a single
chunk of ram and a simple function to access the relevant flags as
single bits. I need to be able to define the different flag names
within their relevent modules because some modules may be removed at
compile time using pre-processor directives.
This code is subject to continuous updating and I just can't find a
bomb proof way of ensuring the values are unique and sequential with no
gaps.

Any ideas?
Thanks
Cliff

May 9 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
us******@btconnect.com wrote:
Hi
Does anyone know if there is a way to define what is effectively a
single globally visible, enumerated list whilst actually defining the
entries across several different modules?
or somehow do a similar thing with macros.

Details:
I have a c project to fit into a small microprocessor and need to save
some ram. I have a significant number of flags all over the place that
currently use whole byte storage. I thought if I had a way to define a
list of numerically sequential flag names, I could assign a single
chunk of ram and a simple function to access the relevant flags as
single bits. I need to be able to define the different flag names
within their relevent modules because some modules may be removed at
compile time using pre-processor directives.
This code is subject to continuous updating and I just can't find a
bomb proof way of ensuring the values are unique and sequential with no
gaps.

Could you use something like

struct flags
{
uint8_t flag1 : 1;
uint8_t flag2 : 1;
uint8_t flag3 : 1;
uint8_t flag4 : 1;
uint8_t flag5 : 1;
};

--
Ian Collins.
May 9 '06 #2

P: n/a
Thanks Ian. I thought of that, but the problem here is that as well as
knowing the flag name I also have to remember which structure i put it
in.
Thanks

May 9 '06 #3

P: n/a
Ian Collins <ia******@hotmail.com> writes:
us******@btconnect.com wrote:
Does anyone know if there is a way to define what is effectively a
single globally visible, enumerated list whilst actually defining the
entries across several different modules?
or somehow do a similar thing with macros.

Details:
I have a c project to fit into a small microprocessor and need to save
some ram. I have a significant number of flags all over the place that
currently use whole byte storage. I thought if I had a way to define a
list of numerically sequential flag names, I could assign a single
chunk of ram and a simple function to access the relevant flags as
single bits. I need to be able to define the different flag names
within their relevent modules because some modules may be removed at
compile time using pre-processor directives.
This code is subject to continuous updating and I just can't find a
bomb proof way of ensuring the values are unique and sequential with no
gaps.

Could you use something like

struct flags
{
uint8_t flag1 : 1;
uint8_t flag2 : 1;
uint8_t flag3 : 1;
uint8_t flag4 : 1;
uint8_t flag5 : 1;
};


The only portable types for bit fields are int, signed int, unsigned
int, and (C99 only) _Bool.

Also, it's likely that accessing a bit field requires more code than
accessing a whole byte. Any savings in data space by packing multiple
flags int a byte might be lost in the increase in code size. (If code
and data are in separate address spaces, the tradeoff is more
complex.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 9 '06 #4

P: n/a
Code space (flash memory) is quite large at 64K, its the ram that's
precious, a meagre 1K. If I could clump the flags together in a single
block then the code to access them would be fairly trivial. Probably
do it as a macro something like (untested):

#define GetFlag(Flag) (FlagRam[(Flag>>3)] & (1<<(Flag&7)) ? 1 : 0

If only I could define those flags :-(

May 10 '06 #5

P: n/a
us******@btconnect.com wrote:
Thanks Ian. I thought of that, but the problem here is that as well as
knowing the flag name I also have to remember which structure i put it
in.


You could put them all in the same one!

--
Ian Collins.
May 10 '06 #6

P: n/a
us******@btconnect.com wrote:
Code space (flash memory) is quite large at 64K, its the ram that's
precious, a meagre 1K. If I could clump the flags together in a single
block then the code to access them would be fairly trivial. Probably
do it as a macro something like (untested):

#define GetFlag(Flag) (FlagRam[(Flag>>3)] & (1<<(Flag&7)) ? 1 : 0


You could use macros such as that or write access functions which would
be smaller, but slower.

First, some compilers, specifically for 8051, which supports bit access,
has a separate data type for a bit variable, which the linker will
allocate for all the linked modules. The 8051 is limited to 128 bits
for direct bit access. Other compiler/linker implementations probably
don't have this level of support for bit variable allocation.

You can use bitfields within each module. It will combine all the bits
within the module into a structure that is rounded up to the next full
increment used for structs, probably 8, 16, or 32 bits.

Here's another approach to save even more space:
Write a preprocessor that will collect declarations from the files that
you will include for a specific build and generate a header file that
defines a structure containing all the bit-fields.

[ Module 1 ]

#ifdef USEGLOBALBITS
#include "globalbits.h"
#else
struct {
int:1 m1flaga;
int:1 m1flagb;
...
} m1flags;
#endif
....
/* use the bit variables */
if (m1flags.m1flaga){
m1flags.m1flagb = 0;
}

[ globalbits.h ]
/* This file is automatically generated. Do not edit. */
struct {
/* declarations from module1.c */
#define m1flags globalflags
int:1 m1flaga;
int:1 m1flagb;
/* declarations from module3.c */
#define m2flags globalflags
int:1 m3flagx;
int:1 m2flagy;
...
} globalbittype;

extern globalbittype globalflags;

The preprocessor would take as parameters the names of the modules to be
included. It would then scan those modules looking for the specific
declarations for globalflags ("#ifndef GLOBALBITS" to "#endif"), picking
out the bit declarations. It defines a single struct containing all the
bitfields. One caveat is that the bitfield names must all be unique.
The strict identifier format used above is not required, so you can use
whatever names you want.

The reason for the #ifdef is that the modules will compile on their own
if USEGLOBALBITS is not defined, but bits from separate modules will not
be combined within a single bitfield. You can use that before you have
the preprocessor working.

When you have the preprocessor working have your script or makefile run
the preprocessor, specifying the modules to be included, then compile
and link the separate code files. Viola -- minimum RAM for bit variables.

The preprocessor doesn't need to be able to do general parsing -- only
recognizing the delimiters for the sections that hold the definitions.

--
Thad
May 10 '06 #7

P: n/a

<us******@btconnect.com> wrote in message
news:11*********************@j33g2000cwa.googlegro ups.com...
Hi
Does anyone know if there is a way to define what is effectively a
single globally visible, enumerated list whilst actually defining the
entries across several different modules?
or somehow do a similar thing with macros.


The usual method with macros is a single master header with OR'able and
AND'able values.

"master.h"
#define ASDF 0x01
#define ASDF 0x02
#define ASDF 0x04
#define ASDF 0x08

Macros can work but get really messy because if you can't #undef until after
the master header is included. This requires the use of alot of extra
defines to calculate the number of useful defines which were defined.

"master.h"
#define OFFSET 0
/* just comment out the one module define you don't need */
/* each central group of macros will be numbered sequentially */
//#define InclMod0 1
#define InclMod1 1
#define InclMod2 1

#ifdef InclMod0
#ifndef OFFSET
#define OFFSET 0
#endif
#define ASDFT (OFFSET)
#define ZXCVC (ASDFT+1)
#define QWERS (ZXCVC+1)
#define DFGHR (QWERS+1)
#ifndef MOD0
#define MOD0 (DFGHR-OFFSET)
#endif
#endif

#ifdef InclMod1
#ifndef OFFSET
#define OFFSET 0
#endif
#ifndef MOD0
#define MOD0 0
#endif
#define ASDF (OFFSET+MOD0+1)
#define ZXCV (ASDF+1)
#define QWER (ZXCV+1)
#define DFGH (QWER+1)
#ifndef MOD1
#define MOD1 (DFGH-OFFSET-MOD0-1)
#endif
#endif

#ifdef InclMod2
#ifndef OFFSET
#define OFFSET 0
#endif
#ifndef MOD0
#define MOD0 0
#endif
#ifndef MOD1
#define MOD1 0
#endif
#define FGH (OFFSET+MOD0+MOD1+1)
#define UIO (FGH+1)
#define QWE (UIO+1)
#define JKL (QWE+1)
#ifndef MOD2
#define MOD2 (JKL-OFFSET-MOD0-MOD1-1)
#endif
#endif

Of course, if I _actually_ needed to do that, I'd definately try to shorten
the names as much as possible.
Rod Pemberton
May 10 '06 #8

P: n/a

Thad, thanks for the suggestion, it looks interresting. I'll
investigate and let you know how I get on.

May 10 '06 #9

P: n/a
Thad. Thanks for your suggestion. I've not actually done it like you
said, but you prompted me in the right direction. The idea of a master
flag file wrapped in some pre-processor defs is the key. Using this I
can achieve my preferred goal of a single global enum list whilst
having the entries defined in separate module headers. This way any
module can see all the flags from all modules.

The only caveats being the names must be unique (as you suggested) and
I must pull in every header with flag definition into the master file.
This is no problem because the compiler won't let me get away with
either of them :-)

I tried it out in a simple dos app and it appears to work fine. I post
the code here for anyone interested.
There is the main code "Main.c", the master flag file
"MasterFlags.h" file plus three modules M1, M2 & M3 (M2 & 3 don't
contain any code).

//--------- Main.c ---------
#include <stdio.h>
#include "M1.h"

#define GET_FLAG_ENUMS
#include "MasterFlags.h"
#undef GET_FLAG_ENUMS

// Define ram to store flags in
unsigned char Flags[ (TOTAL_FLAG_COUNT / 8 ) + 1 ] = {0};

// Test the theory
unsigned char TestEnums[ TOTAL_FLAG_COUNT ];

int main(int argc, char* argv[])
{
int i;
printf("%d Flags Defined\n", TOTAL_FLAG_COUNT );

TestEnums[ 0 ] = M1_Flag_This ;
TestEnums[ 1 ] = M1_Flag_That ;
TestEnums[ 2 ] = M1_Flag_TheOther ;
TestEnums[ 3 ] = M2_Flag_Quick ;
TestEnums[ 4 ] = M2_Flag_Brown ;
TestEnums[ 5 ] = M2_Flag_Fox ;
TestEnums[ 6 ] = M3_Flag_Red ;
TestEnums[ 7 ] = M3_Flag_Green ;
TestEnums[ 8 ] = M3_Flag_Blue ;

for ( i = 0; i < TOTAL_FLAG_COUNT ; i++ )
{
printf( "%d, ", TestEnums[i] );
}
i = M1_Func();
printf( "\ni = %d", i );
scanf("%d",i);

return 0;
}
//---------- END ----------

//------ MasterFlags.h ------
#ifndef MASTERFLAGFILEH
#define MASTERFLAGFILEH

#define GET_FLAG_ENUMS

enum {
#include "M1.h"
#include "M2.h"
#include "M3.h"
TOTAL_FLAG_COUNT
};

#undef GET_FLAG_ENUMS

#endif // MASTERFLAGFILEH
//---------- END ----------

//---------- M1.c ----------

#include "M1.h"

#define GET_FLAG_ENUMS
#include "MasterFlags.h"
#undef GET_FLAG_ENUMS

int M1_Func(void)
{
return M3_Flag_Red; // Can see the enum from M3 :-)
}

//---------- END ----------

//---------- M1.h ----------
#ifdef GET_FLAG_ENUMS
M1_Flag_This,
M1_Flag_That,
M1_Flag_TheOther,
#else

#ifndef M1H
#define M1H

int M1_Func(void); // Prototype

#endif // M1H
#endif // !GET_FLAG_ENUMS
//---------- END ----------

//---------- M2.h ----------
#ifdef GET_FLAG_ENUMS
M2_Flag_Quick,
M2_Flag_Brown,
M2_Flag_Fox,
#else

#ifndef M2H
#define M2H

// Stuff

#endif // M2H
#endif // !GET_FLAG_ENUMS
//---------- END ----------

//---------- M3.h ----------
#ifdef GET_FLAG_ENUMS
M3_Flag_Red,
M3_Flag_Green,
M3_Flag_Blue,
#else

#ifndef M3H
#define M3H

// Stuff

#endif // M3H
#endif // !GET_FLAG_ENUMS
//---------- END ----------

The following results are printed as expected:

9 Flags Defined
0, 1, 2, 3, 4, 5, 6, 7, 8,
i = 6

Regards
Cliff

May 10 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.