#define BYTES *8

B

BartC

Ben Bacarisse said:
Ha! You nearly got me! I'll be honest with you -- I'd commented on
three points before I got that you were joking. If I'd seen it before
my coffee, you'd probably have had a straight answer to chuckle over.

It wasn't a joke ...
 
B

Ben Bacarisse

I count 5, not 8.

If you have a switch case for LT, LE is the same as EQ, no? Maybe I'm
missing your point.

No one can argue against a complaint of "badly defined". Bad how?
Seems fine to me, but obviously not to you.

Why would you allocate a special value for not-equal? How does the
operator decide what to return when a is > b -- the encoding for GT or
the encoding for NE? You've added redundancy to the encoding and
prevented bit-testing.

BTW, if I were doing this I'd make EQ the bottom bit so that the 5 sane
values are compact.

Obviously, in a HLL you just pass the comparison operator directly, but
in C, you could encode the operator from EQ/LT/GT by using 1<<c+1. (The
precedence rules even avoid the need for brackets: 1<<EQ+1 | 1<<LT+1).
Given that this situation is rare, I don't think this is asking too
much. (I'd still be tempted, even in C, to pass a function pointer.)
It wasn't a joke ...

Oh, OK. It was the testing of LE and LT separately that made me think
you were winding me up. Sorry about that.
 
B

BartC

Ben Bacarisse said:
Oh, OK. It was the testing of LE and LT separately that made me think
you were winding me up. Sorry about that.

I didn't think it was a joke because I seriously thought I'd actually
programmed such a thing somewhere or other. But I can't find a trace of it
now! So my apologies.

The nearest I found was a function that at one time returned 100, 010, or
001 binary, to represent lt, eq, gt, (which I later changed to -1,0,1). And
of course the six comparison codes (eq,ne,lt,le,ge,gt) but encoded as a
6-way linear code, and used as an *input*, not an *output* of any comparison
function.

(Having more than 3 comparison codes as a result of a comparison *is*
possible, but as a set, not a linear value: 3<4 might return (le,lt,ne) for
example. But that requires 6 bits, which could be 'switch'-ed on when
interpreted as a 0..63 code, but not what I had in mind...)
No one can argue against a complaint of "badly defined". Bad how?
Seems fine to me, but obviously not to you.

Because you don't know what value will represent not-equal. A bit like
working out what True is in C.
Obviously, in a HLL you just pass the comparison operator directly, but
in C, you could encode the operator from EQ/LT/GT by using 1<<c+1. (The
precedence rules even avoid the need for brackets: 1<<EQ+1 | 1<<LT+1).

OK, so you'd need to construct a special code (and in practice you would
pre-define the 6 compare codes needed).

The problem I was thinking of, was being given a 6-way relative compare code
(one of eq, lt, etc) and 3-way result of comparison (-1, 0 or 1), then
determining if the result is true for the given compare code.

Obviously that can be sorted out given enough code. However, by using this
set of binary codes (similar to my original proposal, but now used as
input):

EQ=010, NE=101, LT=100, LE=110, GE=011, GT=001.

and making the compare function in it's turn return 100, 010, and 001, then
a simple & operation will tell you if the result matches the desired compare
code.
It was the testing of LE and LT separately that made me think
you were winding me up.

That's not so crazy: X<=Y and X<Y could well have different results. But not
in the exclusive form needed to work in a 6-way switch statement.
 
E

Eric Sosman

[...]
(Having more than 3 comparison codes as a result of a comparison *is*
possible, but as a set, not a linear value: [...]

You need a fourth outcome to support NaN, or to support
other "incomparable" things (or "mutually incomparable" if the
language doesn't reconcile mixed types. However, the FORTRAN II
I recall didn't have such issues. I haven't touched any flavor
of FORTRAN/Fortran in decades, and have no idea what the three-
way IF would do with a NaN-valued expression.
 
P

Phil Carmody

Eric Sosman said:
<super-off-topic>

Nope, not gonna work.
Every now and then -- not often, but every now and then --
I find myself longing for the good old three-way IF.

It might get a little clumsy, but there's a compromise
The <=> operator which yields -1, 0, or 1. Your 3-way if
would be a switch on the outcome of that <=>.

I want that in C. Have done for years. Decades, even.

Phil
 
J

John Bode

Anything wrong with that, i.e., with #define BYTES *8
to multiply by 8?

It doesn't read well in the context of regular C code.
Consider:

int x = 10 BYTES;

This scans as "I'm assigning 10 bytes to x"; it does not
scan (at least to me) as "I'm multiplying 10 by
the number of bits in a byte (more correctly, an octet)
and assigning the result to x". I read it as a
descriptive label, not a pseudo-postfix operator.

This simply isn't how C code normally behaves, and
I feel it will be *surprising* (in the bad sense)
to anyone reading it the first time.

If you need to do conversions from one unit to another,
create a function or function-like macro with a name
that *clearly* conveys the nature of the conversion:

#define TO_BITS(x) ( sizeof (x) * CHAR_BIT )
#define TO_BYTES(x) ( (x) / CHAR_BIT )

int x = TO_BITS(10);

It's not pretty, but there's no question of what's
happening here. I'm all for making code scan
more easily, but not at the cost of masking
the underlying operation.

In general, I'm not fond of attempts to use the
preprocessor to fake redefining elements of C
syntax; I've been in that movie more than once,
and it always, always ends in tears.

Will it bite you in the ass from a technical
standpoint? Well, you've already pointed out
the issue with something like

int x = 2 + 2 BYTES;

which, for *this specific conversion*, is probably
the extent of the heartburn you're going to encounter.
It depends on how complex the conversion needs to be,
really.
 
E

Eric Sosman

I might be inclined to go a little further.

#define BYTES_TO_BITS(x) ( sizeof (x) * CHAR_BIT )
#define BITS_TO_BYTES(x) ( (x) / CHAR_BIT )

... which illustrates one of the fundamental problems with
over-enthusiastic abstraction: "I have a three-bit field, so
it occupies BITS_TO_BYTES(3) bytes, right?"
 
B

BartC

If you need to do conversions from one unit to another,
create a function or function-like macro with a name
that *clearly* conveys the nature of the conversion:

#define TO_BITS(x) ( sizeof (x) * CHAR_BIT )
#define TO_BYTES(x) ( (x) / CHAR_BIT )

int x = TO_BITS(10);

This sets x to 32 on my machine. I think it ought to be 80:

#define TO_BITS(x) ((x)*CHAR_BIT)
Will it bite you in the ass from a technical
standpoint? Well, you've already pointed out
the issue with something like

int x = 2 + 2 BYTES;

What's wrong with that? It's 2, plus whatever 2 BYTES is. Just like in
maths.
 
Ö

Öö Tiib

I might be inclined to go a little further.

#define BYTES_TO_BITS(x) ( sizeof (x) * CHAR_BIT )

It is misleading name, should be something like:

#define SIZE_IN_BITS_OF(x) ( sizeof(x) * CHAR_BIT )

#define BITS_TO_BYTES(x) ( (x) / CHAR_BIT )

That is correct name.
 
J

John Bode

This sets x to 32 on my machine. I think it ought to be 80:

#define TO_BITS(x) ((x)*CHAR_BIT)

This is what I get for posting while working on
something else. Of course, you are correct.
What's wrong with that? It's 2, plus whatever 2 BYTES is. Just like in
maths.

Because the multiplication operation is hidden
behind the macro, it's not immediately clear
that there's a precedence issue here. Again,
a casual scan of the code implies that you're
interested in (2 + 2) BYTES, not 2 + (2 BYTES).
 
T

Tim Rentsch

JohnF said:
Anything wrong with that, i.e., with #define BYTES *8
to multiply by 8? It looked a little weird to me, but
the more obvious #define BYTES(x) ((x)*8) isn't what
I wanted to write. This was to express units of measurement,
e.g., int bits = so_many BYTES; rather than
int bits=BYTES(so_many); . I just wanted to read and write
it the first way, and my test program
#define BYTES *8
#include <stdio.h>
int main ( int argc, char *argv[] ) {
int bytes=(argc<2?1:atoi(argv[1])),
bits = bytes BYTES;
printf("%d bytes = %d bits\n",bytes,bits);
return(0); }
works fine (and compiles with no -pedantic warnings).
But that #define BYTES *8 still looks a little funky to me.
I realize 2+2 BYTES must be written (2+2)BYTES, but is there
any other kind of "gotcha"?

Better:

#define BITS_PER_BYTE 8

bits = bytes * BITS_PER_BYTE;

(with the obvious possible improvement involving CHAR_BIT).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top