How to check if value is unique?

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know this is not an avr-gcc specific question - I will now try to abuse the presence of C-knowledgeable experts here.

In a bigger project, I need to assign various *numbers* to different commands. The project involves several different devices and platforms, including AVR and PC, so these *numbers* get naturally defined in different source files. I want these *numbers* to be fixed, assigned manually, rather then generated, to prevent inadvertent shift of a whole range of *numbers*.

I would like to perform some sort of automatic cross-check for uniqueness of these *numbers*. For some reason (poor command of the language :oops: ) I assumed that enum will help me out of the problem... Of course I was wrong, as C99 in 6.7.2.2 says:

Quote:
(The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.)

Any ideas of how to solve this problem?

Thanks,

Jan Waclawek

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That quote simply means that if you use:

typedef enum {
 TYPE0,
 TYPE1,
 TYPE2,
 TYPE3 = 1,
 TYPE4
}

that the value of TYPE1/TYPE3 and TYPE2/TYPE4 will be the same value.

If you don't use '= (or maybe just use it on TYPE0 to set the base to be something other than the default 0) then every item you add to the enum will have a unique value.

Of course if you want really unique numbers use GUID's but they are VERY large!

http://en.wikipedia.org/wiki/Glo...

(you may have noticed these used all over the place in Windows and Linux as "{3F2504E0-4F89-11D3-9A0C-0305E82C3301}" for example)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
That quote simply means...

Yes, of course. What I was trying to say is, that I originally thought, that enum checks for uniqueness, i.e. if in one source (header) I write:

#define COMMAND_DO_SOMETHING 1

and in other source (header) I write:

#define COMMAND_DO_SOMETHING_ELSE 1

then the check can be performed automatically by having a "common header", including both above headers, and perform:

enum {
 TYPE0 = COMMAND_DO_SOMETHING,
 TYPE1 = COMMAND_DO_SOMETHING_ELSE,
}

than if both commands have the same value, the compiler would throw me an error.

The standard says, this is OK, so there is not even a remote chance that some compiler would do this for me.

Before you suggest me to define all COMMANDs in a single source, within a single enum, and possibly using the automatic numbering feature of enum (which now seems to be its only purpose, as standard C does not enforce it as a type): this was just an oversimplified example of what I was expecting from enum, and my real case is way more complex than that. I have reasons to define the COMMANDs separately, and, as some groups of COMMANDs *may* overlap, I want to perform a SET of various crosschecks (i.e. I would have more such enum-s, would enum do what I want).

So, let the question be, whether there is some construction in C, which takes an arbitrary number of constants (possibly hidden behind preprocessor #defines); and which would warn me, if two of those constants would be of the same value.

clawson wrote:
Of course if you want really unique numbers use GUID's

No, of course, this is not what I want; but thanks for the hint, it may come handy.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Before you suggest me to define all COMMANDs in a single source, within a single enum, and possibly using the automatic numbering feature of enum

I misunderstood - I thought THIS was exactly what you were planning in the first place.

Short of a humungous chunk of cross-checking #if's I'm not sure I can see how you could guarantee uniqueness at pre-processing time. I would probably just try and collect all the COMMAND_???'s together in a single .h and #define them sequentially (or rather at least uniquely in an ordered list)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Short of a humungous chunk of cross-checking #if's

Bleeeeeh... :-P
clawson wrote:
I'm not sure I can see how you could guarantee uniqueness at pre-processing time. I would probably just try and collect all the COMMAND_???'s together in a single .h and #define them sequentially (or rather at least uniquely in an ordered list)

This still does not solve the problem of multiple lists, of which some may overlap and others must not (and, of course, I want to use the "namespaces" as fully as possible, to reduce the number of transferred bits).

But I am ready to write an utility on my own, as long as it won't involve complete parsing of the sources. Any idea how to conveniently emit a list of values of enum's members?

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Uh, I'd just use enum table in one file, and include it into both AVR and PC software as header. If you don't set the enum values yourself, they will be continuous, and no number is same as another.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jepael wrote:
Uh, I'd just use enum table in one file, and include it into both AVR and PC software as header. If you don't set the enum values yourself, they will be continuous, and no number is same as another.

Side-stepping the problem won't help me.

I WANT to set them manually, and I WANT to check values set elsewhere. This IS the case to do it.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jepael's suggestion seems to be the wisest. You can re-assign the enum counter whenever you like. ( as in Cliff's example )

You can put all your platform-specific conditionals in this enum table as well.

Which should leave you nice clean code in your regular C files.

Mind you, your "master_enum.h" file will require careful checking.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Jepael's suggestion seems to be the wisest.

Nah, it solves a different problem than I have. Believe me, I DO have reasons why I ask for a solution to a specific problem.

david.prentice wrote:
Which should leave you nice clean code in your regular C files.

I am THE C-hater, remember? ;-) On PC, I use Pascal, for example, wherever possible.

david.prentice wrote:
Mind you, your "master_enum.h" file will require careful checking.

That's exactly why I want to leave it to the machine to check.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wek wrote:

I am THE C-hater, remember? ;-) On PC, I use Pascal, for example, wherever possible.

Do you use Lazarus by the way? I've recently started to use it because there is no software with comparable stability for C GUI programming.

Well you could make a some kind of file by hand or with Excel (well on Openoffice too, preferably) and save it as text file and do some macros that convert the file to C header and Pascal "header".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you setup a switch statement with a case for each number, a compiler should complain if there is a duplication.
Dave Raymond

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I DO have reasons why I ask for a solution to a specific problem.

We've seen this game being played here a lot over the years. The pattern is
Question: I want to do X and exactly X [no or weak reason given]
Answers: [guessing about the underlying rationale] OK, you could do it like this [sketchy solution]
Q: No, that wont do, I need exactly X.Y [still with the ultimate rationale not told]
A: [guessing ans speculating, again] OK you could [new suggested solution]
and it goes on, and on...

Why not just tell us what the exact and ultimate problem is?

Either this project is of hobby nature, in which case you can reveal it all.
Or it is a professional project, in which case you should be able to describe "the pattern" without revealing what you are working on.

The fina possibility is that you have an absolutely brilliant idea for something that you will patent, and that will earn you millions. In that case you should solve it all by yourself, of be willing to share the profit with us.. :)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"How to check if value is unique?"

Reminds me of this old one:

"How do you catch a unique rabbit?" "You 'neak up on it."
"How do you catch a tame rabbit?" "The tame way!"

[enum perhaps with a bit of pre-processor sounds good to me]

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Untested, but:

#define COMMANDS1 DO_SOMETHING, DO_SOMETHING_MORE
#define COMMANDS2 DO_SOMETING_ELSE, DO_YET_ANOTHER_THING
enum {
  START_TOKEN = 0, // force a 0 start
  COMANNDS1,
  COMMANDS2 
} 

This should result in unique values for each named command, as the values are auto-assigned, by incrementing from START_TOKEN.

Having said that... the system relies on the exact order, number of commands, and sequence of inclusions to be identical for all platforms.

Look into how IOCTL commands are generated in Linux. This should be more flexible, and easier to manage. Also can remain backwards compatible if additional commands are added later on.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jepael wrote:
Do you use Lazarus by the way?

I did some project using Lazarus quite recently: a very dirty graphics editor for a 240x64 GLCD, which is on the box I am working at (among others) at the moment. The point was, as you draw on the PC screen, at the same moment it draw also on the GLCD (the box is connected via USB to the PC). Text input, cut&paste and that stuff.

But I wouldn't describe myself as a PC programmer, so I don't want to comment on the quality of Lazarus/FreePascal. Most of the stuff I do on PC are just utilities I need for my work, I wouldn't give them away. Most of that is command line, so I don't need whole Lazarus, I use FreePascal quite regularly now (and not even its IDE, at the moment I find to easier to use a single editor for all my work, including the AVR stuff).

Jepael wrote:
Well you could make a some kind of file by hand or with Excel (well on Openoffice too, preferably) and save it as text file and do some macros that convert the file to C header and Pascal "header".

I have mentioned that I write most of my programs today in a xml-based meta-language inspired by Knuth's WEB, I call nyweb, and I generate the sources out of these, so I might be able to do all that stuff using just my own tools. Today, I wrote a feature request to myself (a bit of schizofreny... ;-) ) to support unique-check of the lists feature of nyweb (which are unfortunately still on the wishlist, too).

But, since that backlog won't get cleared until I finish the job of the day, I was seeking for something readily available.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

draymond wrote:
If you setup a switch statement with a case for each number, a compiler should complain if there is a duplication.

Humm.
With a certain switch, yes (it's not a standard C behaviour IIRC).

You mean, to add a dummy source file with the switch, and then throw it away? Interesting idea, this might be what I am looking for.

Thanks,

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Why not just tell us what the exact and ultimate problem is?

The exact and ultimate problem is, how to test compile-time, whether two set of constants do or don't overlap... :-)

JohanEkdahl wrote:
The final possibility is that you have an absolutely brilliant idea for something that you will patent, and that will earn you millions. In that case you should solve it all by yourself, of be willing to share the profit with us.. :)

Rest assured I won't give a single penny out of those millions to neither of you... :-P

---

Oh I have no problem giving the details - it's just waste of time. But you asked for it... :-) The problem is, that I don't know what the problems might be in the future, and I am trying to prevent as much of them as possible now. Having maintained a certain project for more than a decade, including porting it to a completely different platform several times, expanding its size to several times of the original, producing a set of associated/accompanying/servicing projects; I recognize the value of a set/list of stable and permanent constants for a certain purpose. Believe me or not, the best thing we came up was a paper list of commands, with hand-scribbled addenda and corrigenda, torn and worn, carefully packed up into a file (the real stuff, not the abstract one). It had a .doc prototype somewhere, and it was updated once in a few years, but the ultimate one was always the paper. We kept the original one very carefully, even when it was hopelessly obsolete, but all the information it contained was still valid (albeit incomplete), because it was brief enough to serve as a quick reference (it was only a couple of pages whereas the latest full one run tens of pages long). It was perfectly usable across all the platforms associated with the project, readily available (as long as some of my colleagues did not trow THE file into a locked drawer), easy to update, and we always knew which one is THE ultimate source. And all the versions of all devices were based on the same command set, making them 100% backwards compatible, which is a big thing if you have a bunch of them out there and users are mixing them freely. Think Internet and the "assigned numbers" RFC/STD (and IANA).

Now I am in the position of startin a similarly sized project, with a big chance that it will grow into unexpected directions in the future few months or years. The list in question is a set of commands on a multimaster bus. Everyone is talking to everyone (not exactly, but sort-of). We estimated, that 8 bits of command should suffice, and although the protocol can implement some "command stretching" mechanism, this would be potentially problematic, as the communication is relatively fast. I want to make the best possible use of the available "namespace", to prevent shortage of commands in the future.

So, imagine, that A has commands to tell to B (i.e., addressed), let's assign them Cab; B has a different set of commands to tell to A, Cba. It's easy to see that Cab may fully overlap Cba. Now C has commands for both A and B and vice versa. Cca cannot overlap with Cba, etc. - but so far, it's relatively simple - if we group the commands by addressee, these are the commands that may not overlap.

Now we have also broadcasts, Cbroa, which can overlap any other group, as they have a unique "broadcast" address. Simple, huh?

Now come the problematic ones: it turns out, that from viewpoint of D, A and B are the same, so we want Cda to be the same as Cdb, but they must not overlap any other Cxa and Cxb. Also, as an option, a simplified version of B and C can be implemented as a single box, so we now want a sub-group of Cxb and Cxc not to overlap. We considered a "redirectable" command, i.e. C says something to B, but B finds out it's now A's reponsibility, so B simply retransmits the message to A - this command must be present in both A's and B's command set but not overlap with the rest of their commands.

And, once a command has an assigned value, a number, we don't want it to change, ever; and we want to use a symbolic name for it. That we want to be able to define the commands in different files (namely, headers), it's just a secondary and relatively minor issue.

See, it is easy to establish firm rules for the check, but given a large enough number of devices and commands and command groups, the task is not fit for a human.

Is this a good enough description of the problem?

---

As I wrote, I seek a ready solution. I can come up with my own; I just don't have the time. I thought, enum will do the job, it turned out, it won't. I will think over the switch-based one during the nigh, but it sounds like that's it.

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

We estimated, that 8 bits of command should suffice, and although the protocol can implement some "command stretching" mechanism, this would be potentially problematic, as the communication is relatively fast.

Sounds like the IPV4 vs IPV6 situation. Maybe start with 16 bit commands? You can then divide it into 256 lots of 256 and each sub-module can grow it's own command set up to a max of 256 - IOW built in "slack" for expansion.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

We estimated, that 8 bits of command should suffice, and although the protocol can implement some "command stretching" mechanism, this would be potentially problematic, as the communication is relatively fast.

Sounds like the IPV4 vs IPV6 situation. Maybe start with 16 bit commands? You can then divide it into 256 lots of 256 and each sub-module can grow it's own command set up to a max of 256 - IOW built in "slack" for expansion.

Yes and no. The timing is tight, and 8 bits is already a convenience. The original proposal called for command length stretchable by non-multiple-of-8 number of bits, depending on the "importance" of each particular command; and a similar mechanism for addressing - but the complexity involved in this would be undoubtedly several orders of magnitude higher than it is now.

The problem with explaining the design decisions in fora like this is, that one never knows where to stop. I a asking myself, ocassionally, why did I decide to go for electronics and programming at all... :-?

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The exact and ultimate problem is, how to test compile-time, whether two set of constants do or don't overlap...

No, that is not the ultimate problem, which can easily be demonstrated by asking "Why does it have to be two sets?".

My point was that answers to questions sometimes try to make the OP think outside of the box he seems to be in currently, and surprisingly often the OP is defending this box quite furiously. Not sure if that applies to your case or not.

(I suddenly came to think of The French Knights in the film The Wholy Grail by Monty Python. I sort of envisioned some OP, not necessarily you, sitting in an upside down carboard box where the edges has been cut to resemble the edges of a medeival castle, throwing posts down at seasoned 'freaks and yelling "You freakish kniggets!", "Your breadboard is a hamster and your JTAG smells of elderberry!", "Fetes le PIC!" etc etc. Hilarious for me - prolly not so for you..)

[Preparing to stay and die poor :) ]

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Quote:

The exact and ultimate problem is, how to test compile-time, whether two set of constants do or don't overlap...

No, that is not the ultimate problem, which can easily be demonstrated by asking "Why does it have to be two sets?".

Johan,

I appreciate your help. The problem with this game is, that 1. you never know how stiff the box is, as it's not your box; 2. once the OP climbs out of the box, he finds himself inside an other, maybe bigger, maybe stiffer, but maybe weaker, box.

If you had the patience to read my long writeup above, you probably know, why it has/should/ought/is wished to be two sets. As one possible way out of the box, clawson suggested to extend the namespace to 16 bits, where non-overlapping sets would be ensured trivially. This hits the box of communication speed limits. It's just natural to question the stiffness of communication speed box. This results in a complex reasoning basically boiling down to cost of components. The following box is thus the marketing one, and the way out of it asking for richer customers; and ultimately you can question why the hell did we decide to make money out of making electronic gadgets, once having a farm and NOT growing anything pays out much more today, thanks to the EU subsidies... ;-)

[Preparing to stay and die poor :) ]

It's not necessary. Come up with your $1M idea, pay us the toll, and you can live happily with the remainder for the rest of the years... :-P

Jan