enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
On Wednesday, October 24, 2018 at 1:18:20 PM UTC+2, pozz wrote:[...]
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
What is your strategy?
Long answer: read the definition of "enumeration"
Short answer:
An enumeration is a normal type disguised and is implementation dependent. Usually is signed int (whatever it means) but you have to check your compiler doc to be sure.
You can also explicitly set the value of every member of an enum:
(and if you use an enum in a packet that is sent to someone else it may be a very good idea to do so)
enum type_t {
TYPE_1 = 34,
TYPE_2 = 56,
TYPE_3,
TYPE_4 = 0,
TYPE_5 = 0,
TYPE_100,
}
Exercise left to the reader: what's the value of TYPE_3 and TYPE_100?
If you need to send something to someone else there is a thing called "protocol" that explain in detail (hopefully) what's inside every byte you send. If for some reason the protocol changes...both transmitter and receiver needs to be modified.
On 24/10/18 13:18, pozz wrote:
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
It doesn't matter whether you are sending "raw" integers, enumerations,
text strings, lead balloons - the sender and the receiver need to agree
on the protocol and the messages sent. The easiest way is to make sure things like your enumeration here are in a common header that both the receiver and the transmitter include in their code - then it is hard to
get out of sync.
It can also be worth including some sort of version information in the initial handshake of the protocol - any changes in the enumeration or
other details should be accompanied by a change in the version number,
so that the other end can see that something has changed.
Il 24/10/2018 15:10, David Brown ha scritto:
On 24/10/18 13:18, pozz wrote:
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
It doesn't matter whether you are sending "raw" integers, enumerations,
text strings, lead balloons - the sender and the receiver need to agree
on the protocol and the messages sent. The easiest way is to make sure
things like your enumeration here are in a common header that both the
receiver and the transmitter include in their code - then it is hard to
get out of sync.
It can also be worth including some sort of version information in the
initial handshake of the protocol - any changes in the enumeration or
other details should be accompanied by a change in the version number,
so that the other end can see that something has changed.
The problem here is not to share a new version of the protocol, but to
avoid that a developer could change some part of the code (an
enumeration) and broke the protocol *inadvertently*.
Il 24/10/2018 13:45, Jack ha scritto:
On Wednesday, October 24, 2018 at 1:18:20 PM UTC+2, pozz wrote:[...]
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
What is your strategy?
Long answer: read the definition of "enumeration"
Short answer:
An enumeration is a normal type disguised and is implementation
dependent. Usually is signed int (whatever it means) but you have to
check your compiler doc to be sure.
These details are generally important, but not for my question. I don't
know if C standard guarantees that, if not specified, the first value is
zero and the others are contiguous. If it is guaranteed, my example
above works. Otherwise, the declaration of my enumeration should have
been:
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
On Wed, 24 Oct 2018 13:18:15 +0200, pozz wrote:channel.
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
Your protocol document defines what is sent on the communications
In your code you may have:
enum type_t {
TYPE_2,
TYPE_1,
...
TYPE_100
}
But in your protocol handler you have
enum protocol_type_t {
PTYPE_1,
PTYPE_2,
...
PTYPE_100
}
switch(t) {
case TYPE_1:
tx_byte(PTYPE_1);
.....
You convert your internal type_t to the external protocol protocol_type_t and protocol_type_t always (well should always) matches the spec.
Il 24/10/2018 15:10, David Brown ha scritto:
On 24/10/18 13:18, pozz wrote:
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
It doesn't matter whether you are sending "raw" integers, enumerations,
text strings, lead balloons - the sender and the receiver need to agree
on the protocol and the messages sent. The easiest way is to make sure
things like your enumeration here are in a common header that both the
receiver and the transmitter include in their code - then it is hard to
get out of sync.
It can also be worth including some sort of version information in the
initial handshake of the protocol - any changes in the enumeration or
other details should be accompanied by a change in the version number,
so that the other end can see that something has changed.
The problem here is not to share a new version of the protocol, but to
avoid that a developer could change some part of the code (an
enumeration) and broke the protocol *inadvertently*.
Il 24/10/2018 19:48, Joe Chisolm ha scritto:
On Wed, 24 Oct 2018 13:18:15 +0200, pozz wrote:
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
Your protocol document defines what is sent on the communicationschannel.
In your code you may have:
enum type_t {
TYPE_2,
TYPE_1,
...
TYPE_100
}
But in your protocol handler you have
enum protocol_type_t {
PTYPE_1,
PTYPE_2,
...
PTYPE_100
}
switch(t) {
case TYPE_1:
tx_byte(PTYPE_1);
.....
You convert your internal type_t to the external protocol protocol_type_t and protocol_type_t always (well should always) matches the spec.
Yes, it seems *THE* best solution in order to avoid problems. Even if
it is tedious, because you have two enumerations instead of one and you
have a long piece of translation code that is silly.
On Wed, 24 Oct 2018 13:18:15 +0200, pozz wrote:
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
Your protocol document defines what is sent on the communications channel.
In your code you may have:
enum type_t {
TYPE_2,
TYPE_1,
...
TYPE_100
}
But in your protocol handler you have
enum protocol_type_t {
PTYPE_1,
PTYPE_2,
...
PTYPE_100
}
switch(t) {
case TYPE_1:
tx_byte(PTYPE_1);
....
You convert your internal type_t to the external protocol protocol_type_t
and protocol_type_t always (well should always) matches the spec. If the code
passes a type_t that does not match a protocol_type_t you have a error and about
to violate the protocol - logs and alarms happen. It's up to the receiver to decide what to do if a protocol_type_t does not match a value it can deal with.
If your protocol says protocol_type_t is sent as 8 bits I think it's a good idea
to fill out the enum with all 256 possibilities defined.
PTYPE_100,
SPARE_PTYPE_101,
SPARE_PTYPE_102,
...
The protocol doc defines what PTYPE_1 to PTYPE_100 mean and notes 101 to max value
are reserved for future use.
On 24/10/18 19:48, Joe Chisolm wrote:
On Wed, 24 Oct 2018 13:18:15 +0200, pozz wrote:
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
Your protocol document defines what is sent on the communications channel. >> In your code you may have:
enum type_t {
TYPE_2,
TYPE_1,
...
TYPE_100
}
But in your protocol handler you have
enum protocol_type_t {
PTYPE_1,
PTYPE_2,
...
PTYPE_100
}
switch(t) {
case TYPE_1:
tx_byte(PTYPE_1);
....
You convert your internal type_t to the external protocol protocol_type_t
and protocol_type_t always (well should always) matches the spec. If the code
passes a type_t that does not match a protocol_type_t you have a error and about
to violate the protocol - logs and alarms happen. It's up to the receiver to >> decide what to do if a protocol_type_t does not match a value it can deal with.
If your protocol says protocol_type_t is sent as 8 bits I think it's a good idea
to fill out the enum with all 256 possibilities defined.
PTYPE_100,
SPARE_PTYPE_101,
SPARE_PTYPE_102,
...
The protocol doc defines what PTYPE_1 to PTYPE_100 mean and notes 101 to max value
are reserved for future use.
I can't help thinking this is extremely inefficient, and completely unnecessary.
In reality, in a small system you might have perhaps a dozen different message types - "protocol types". Make an enum for these. Make documentation for them (which will use the real numbers). Have a little static assert at the end of the enum definition to make sure you have
not missed one out by accident. Put the enum definition, and other protocol-related common declarations, in a single header that is shared
by both the client and server sides. If the client programmers and the server programmers get mixed up versions or make their own independent changes, fire the project manager (not the programmers).
All this extra code - the endless unnecessary declarations of "spare"
values, the vast useless switches - they are nothing but magnets for
errors, typos, copy-and-paste errors, maintenance nightmares, and are
going to be completely untestable.
On 24/10/18 19:48, Joe Chisolm wrote:
On Wed, 24 Oct 2018 13:18:15 +0200, pozz wrote:
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast >>> to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
Your protocol document defines what is sent on the communications channel. >> In your code you may have:
enum type_t {
TYPE_2,
TYPE_1,
...
TYPE_100
}
But in your protocol handler you have
enum protocol_type_t {
PTYPE_1,
PTYPE_2,
...
PTYPE_100
}
switch(t) {
case TYPE_1:
tx_byte(PTYPE_1);
....
You convert your internal type_t to the external protocol protocol_type_t
and protocol_type_t always (well should always) matches the spec. If the code
passes a type_t that does not match a protocol_type_t you have a error and about
to violate the protocol - logs and alarms happen. It's up to the receiver to >> decide what to do if a protocol_type_t does not match a value it can deal with.
If your protocol says protocol_type_t is sent as 8 bits I think it's a good idea
to fill out the enum with all 256 possibilities defined.
PTYPE_100,
SPARE_PTYPE_101,
SPARE_PTYPE_102,
...
The protocol doc defines what PTYPE_1 to PTYPE_100 mean and notes 101 to max value
are reserved for future use.
I can't help thinking this is extremely inefficient, and completely unnecessary.
In reality, in a small system you might have perhaps a dozen different message types - "protocol types". Make an enum for these. Make documentation for them (which will use the real numbers). Have a little static assert at the end of the enum definition to make sure you have
not missed one out by accident. Put the enum definition, and other protocol-related common declarations, in a single header that is shared
by both the client and server sides. If the client programmers and the server programmers get mixed up versions or make their own independent changes, fire the project manager (not the programmers).
All this extra code - the endless unnecessary declarations of "spare"
values, the vast useless switches - they are nothing but magnets for
errors, typos, copy-and-paste errors, maintenance nightmares, and are
going to be completely untestable.
On Thu, 25 Oct 2018 09:31:47 +0200, David Brown wrote:
I can't help thinking this is extremely inefficient, and completely
unnecessary.
switch(t) {
case TYPE_1 ... TYPE_100:
out=table[t]; // table being defined for values of t in the range
break;
case TYPE_101 ... TYPE_256:
error_log();
break;
default:
worse_error_log();
break;
}
Even having
case TYPE_1:
blah
case TYPE_2:
blah
...
case TYPE_101:
case TYPE_102:
case TYPE_103:
error_log();
break;
default:
worse_error_log();
break;
}
a good compiler is going to roll all that together.
In reality, in a small system you might have perhaps a dozen different
message types - "protocol types". Make an enum for these. Make
documentation for them (which will use the real numbers). Have a little
static assert at the end of the enum definition to make sure you have
not missed one out by accident. Put the enum definition, and other
protocol-related common declarations, in a single header that is shared
by both the client and server sides. If the client programmers and the
server programmers get mixed up versions or make their own independent
changes, fire the project manager (not the programmers).
And eventually this gets shipped and you have a customer with version 1
box talking to a version 2 box talking to a version 3 box because they
dont want to update all the boxes at the same time.
The protocol
handler is a black box that you can unit test with a reasonably robust
test harness. That test suite validates the protocol and gives you a
known base. Transmitter test vectors are compared against receiver test vectors. Once built these test suites only have to be changed if the protocol changes but get used in verification for each release. If it
is duplex you have a->b vectors and b->a vectors.
All this extra code - the endless unnecessary declarations of "spare"
values, the vast useless switches - they are nothing but magnets for
errors, typos, copy-and-paste errors, maintenance nightmares, and are
going to be completely untestable.
That's because you live in the old world of actually typing all this
stuff in. You have abundant tools at your disposal to create this
code. You have a input file of some type, a state diagram or other "document" for the protocol and your tools auto create the code from that. The make file auto generates the headers and code. Hell, even lowly
awk can generate code for you. 20 years ago we were using simple
tools to take register definition files and spit out VHDL and C
headers and functions. We did the same thing with a CAN bus protocol.
This is robot work, make the computer do it.
enum type_t {
TYPE_1,
TYPE_2,
...
TYPE_100,
}
void tx_byte(unsigned char c);
enum type_t t;
...
tx_byte((unsigned char)t);
If the maximum value in the enumeration is lower than 256, you can cast
to (unsigned char) and transmit it as a byte.
However the receiver must have the same enumeration. The transmitter
and the receiver must agreed on *the exact values* of the enumeration.
What happens if the developer of the transmitter thinks that it is
better to swap some values during a future release? The enumeration
isn't used only for transmission, it is also used for general logic of
the software.
Until now I didn't found a good solution. I only write some comments
before the enumeration declaration:
/* WARNING!! DON'T CHANGE THE ORDER OF THE VALUES INSIDE ENUMERATION
* They are also used in the transmission */
I sometimes prefer explicit the value transmitted:
if (t == TYPE_1) tx_byte(0);
if (t == TYPE_2) tx_byte(1);
...
What is your strategy?
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,064 |
Nodes: | 10 (0 / 10) |
Uptime: | 148:16:11 |
Calls: | 13,691 |
Calls today: | 1 |
Files: | 186,936 |
D/L today: |
33 files (6,120K bytes) |
Messages: | 2,410,934 |