#define BYTES *8

J

JohnF

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"?
 
M

Mark Bluemel

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"?

I hate the name - it doesn't actually convey the intent to my mind.
 
K

Keith Thompson

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"?

I'd say it violates the principle of least surprise. Seeing an
identifer used that way, effectively as a postfix unary operator, is
confusing; it's very difficult to understand unless you examine the
definition of the macro.

Most macros can be understood, in terms of their meaning if not their
implementation, by looking at their names and arguments.

Something similar: Years ago, I thought that this:

#define EVER (;;)

was clever, because I could write:

for EVER {
/* ... */
}

I still think it's clever. I just no longer think that's a good thing.

And as Mark Bluemel indicates, the name doesn't convey the meaning well.
It says that you're working with bytes somehow, but it doesn't imply
anything about a conversion to bits.

If you want to compute the number of bits in a given number of bytes,
and you're using the word "byte" as it's defined by the C standard, then
you need to multiply by CHAR_BIT, defined in <limits.h>:

bits = bytes * CHAR_BIT;

That's clear enough that no additional macro is needed.
 
J

JohnF

Keith Thompson said:
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"?

I'd say it violates the principle of least surprise. [...]
[...] If you want to compute the number of bits in a given
number of bytes,
bits = bytes * CHAR_BIT;
That's clear enough that no additional macro is needed.

My bad. The actual app involves physical units. I just used
bits/bytes as an example for the post. Moreover, the actual
program is user-modifiable at compile time by way of an
#include "userformulas.h" in the middle of the code (not as
a header) containing stuff like length=10 feet; width=3 inches;
height=4 meters; etc; (And please don't tell me that
should be input as data. The alternatives were considered
and the decision's been made.) So you can see why I want
to do this. And the aspect of the semantics you're talking
about isn't really relevant. The only question I'm asking
is about any straightforward semantic problems arising from
the funky-looking syntactic construction.
 
B

BartC

My bad. The actual app involves physical units. I just used
bits/bytes as an example for the post. Moreover, the actual
program is user-modifiable at compile time by way of an
#include "userformulas.h" in the middle of the code (not as
a header) containing stuff like length=10 feet; width=3 inches;
height=4 meters; etc;

I use the same thing elsewhere:

x = 3m+50cm

so x ends up as 3500 when the basic unit is mm (m scales by 1000, and cm by
10).

So it sounds reasonable enough and using #define as you have sounds like the
closest you might get in C source code.

However:

o I only use such a suffix after a constant
o It only applies to the immediately preceding constant

So your 2+2 BYTES example elsewhere would need to be written as 2 BYTES + 2
BYTES, which makes more sense anyway.
The only question I'm asking
is about any straightforward semantic problems arising from
the funky-looking syntactic construction.

Without proper language support, your macro could be used in ways that were
not intended (2 BYTES BYTES BYTES for example).
 
J

JohnF

BartC said:
I use the same thing elsewhere: x = 3m+50cm
so x ends up as 3500 when the basic unit is mm
(m scales by 1000, and cm by 10).
So it sounds reasonable enough and using #define as you have
sounds like the closest you might get in C source code.

Thanks, Bart. I figured it would work because I tested it
and it worked. But I still wanted to double-check becuase
it looked strange, and I'd never used that kind of #define
construction before, nor seen similar stuff used.
In fact, full disclosure, it would never have occurred
to me except I saw /mm {2.834646 mul} def in some
postscript code (who knew there were 2.83 seventy-seconds
of an inch in a mm?).
 
J

James Kuyper

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"?

It's a bad idea because it works in a way very different from C
identifiers that are not macros. The best uses of macros always mimic
other kinds of identifiers syntactically. However, there's another issue
as well, even if we accept the the way you want to use this macro, it's
defined wrong. It should, for the sake of portability, be

#include <limits.h>
#define BYTES *CHAR_BIT
 
T

tom st denis

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

As others pointed out the name is a bit confusing as "bytes" is not
what it counts but bits.

But more so it's probably better to have something like

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

Which is both named correctly, uses the correct bit definition, and
doesn't have unintended side effects.

Tom
 
B

BartC

Scott Fluhrer said:
Whether this last part is good advice depends on what the original
programmer is trying to do.

Apparently he wants to apply a scale factor to a quantity, by using the
macro as a suffix to the quantity.
 
I

ImpalerCore

As others pointed out the name is a bit confusing as "bytes" is not
what it counts but bits.

But more so it's probably better to have something like

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

Which is both named correctly, uses the correct bit definition, and
doesn't have unintended side effects.

I prefer 'c_sizeof_bits' (the 'c_' is the prefix I use for my stuff),
which helps remind me that the macro is an extension of the sizeof
operator. I use 'c_sizeof_array' for similar reasons. I was tempted
to use all caps, but I wanted to adopt the same case-style as 'sizeof'
for these two macros.

Best regards,
John D.
 
K

Keith Thompson

Scott Fluhrer said:
Whether this last part is good advice depends on what the original
programmer is trying to do. If he really does mean 'the number of bits in
the platform-dependent char type', then yes, this works well. However, if
he mearns 'the number of bits within a platform-independent octet' (for
example, what's actually transmitted over TCP), this is less good.

Remember, the meaning that C assigns to the word 'byte' isn't the only
meaning that word can have.

Then calling it OCTETS rather than BYTES would improve clarity.
 
E

Eric Sosman

On 8/28/2012 4:38 AM, Keith Thompson wrote:
[...]
Something similar: Years ago, I thought that this:

#define EVER (;;)

was clever, because I could write:

for EVER {
/* ... */
}

I still think it's clever. I just no longer think that's a good thing.

:)

Perhaps:

#define FOREVER for(;;)

Not that I'd ever use such a thing, of course. Still clever. Still
"not really a good thing to do".

In my own young and foolish days, I used

#define until(x) while(!(x))

believing it improved readability. Foolishness never leaves us
altogether, but youth and inexperience do -- and clevernesses of
this kind went into my personal "Wish I'd never done that" file
long ago. (Right next to the FORTRAN II code that avoided an IF
by using a computed GOTO.)
 
A

Adrian Ratnapala

In my own young and foolish days, I used

#define until(x) while(!(x))

believing it improved readability. Foolishness never leaves us

I wouldn't do that in C, but the "until" is one of the things that I did
enjoy about Perl.
 
J

Joe Pfeiffer

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"?

That way lies madness. Using macroes to invent new syntax for C is a
Bad Idea. It looks good when you come up with it, it looks good when
you first code it up, it turns out to be a disaster some time down the
road when you're maintaining it. There's nothing particularly wrong
with the specific macro you're suggesting (except possible surprises
with operator precedence), but typically when people do that they also
define a bunch of other similar macroes that turn into a nightmare.

Yes, I did once define a macro

#define EVER (;;)

but I was much, much younger then.
 
E

Eric Sosman

On 8/29/2012 11:10 AM, Kenneth Brody wrote: [...]
Perhaps:

#define FOREVER for(;;)

Not that I'd ever use such a thing, of course. Still clever. Still
"not really a good thing to do".

In my own young and foolish days, I used

#define until(x) while(!(x))

believing it improved readability. Foolishness never leaves us
altogether, but youth and inexperience do -- and clevernesses of
this kind went into my personal "Wish I'd never done that" file
long ago. (Right next to the FORTRAN II code that avoided an IF
by using a computed GOTO.)

Ah. You must have read that famous article "If Considered Harmful".

<off-topic>

Perhaps you overlooked the Roman numeral. In those days,
FORTRAN's only IF had the form

IF ( expression ) n1, n2, n3

.... with the meaning: "GOTO statement number `n1', `n2', or `n3'
as `expression' is negative, zero, or positive." Thus

IF (X) 1, 2, 1

.... was a zero/nonzero test,

IF (X) 1, 2, 2

.... was a negative/nonnegative test, and so on. IF(X) 1,1,1
was a plain old unconditional GOTO 1 in disguise.

FORTRAN IV added an alternate kind of IF that was closer to
what we find in C -- but only a little bit closer.

<super-off-topic>

Every now and then -- not often, but every now and then --
I find myself longing for the good old three-way IF. A binary
search needs two of these newfangled two-way `if' tests where
one three-way test would suffice, and a similar situation crops
up in the inner loop of Heapsort. Ah, well: Change (even change
for the better) always involves loss.

</super-off-topic>
</off-topic>
</maudlin-reminiscence>
 
B

Ben Bacarisse

Eric Sosman said:
<off-topic>

Perhaps you overlooked the Roman numeral. In those days,
FORTRAN's only IF had the form

IF ( expression ) n1, n2, n3

... with the meaning: "GOTO statement number `n1', `n2', or `n3'
as `expression' is negative, zero, or positive." Thus

IF (X) 1, 2, 1

... was a zero/nonzero test,

IF (X) 1, 2, 2

... was a negative/nonnegative test, and so on. IF(X) 1,1,1
was a plain old unconditional GOTO 1 in disguise.

FORTRAN IV added an alternate kind of IF that was closer to
what we find in C -- but only a little bit closer.

<super-off-topic>

Every now and then -- not often, but every now and then --
I find myself longing for the good old three-way IF. A binary
search needs two of these newfangled two-way `if' tests where
one three-way test would suffice, and a similar situation crops
up in the inner loop of Heapsort. Ah, well: Change (even change
for the better) always involves loss.

I, too, missed it on occasion, but then I got it back! In Haskell, any
type that "inherits" from Ord (all ordered things, in effect) provides a
'compare' function that returns EQ, LT or GT. You then "switch" on the
result. (Scare quotes because Haskell names everything differently.)

Given that C's comparisons (struggling to get topical again) already
produce ints, it would not have seemed odd to have provided, say, <>
that yields -1, 0 or 1 in the expected way. If strcmp and friends had
been similarly constrained, these value could have been sensible named
CMP_LT, CMP_EQ and CMP_GT (or whatever) and we could switch on them with
no magic numbers in sight.
 
J

JohnF

Ben Bacarisse said:
...struggling to get topical again...
I, the op, hereby grant dispensation to all persons
in this thread to get as far off-topic as they like.
 
B

BartC

Ben Bacarisse said:
Eric Sosman <[email protected]> writes:

(But sounds like an extra subtraction is needed to yield a single 3-way
value.)
, and a similar situation crops

I, too, missed it on occasion, but then I got it back! In Haskell, any
type that "inherits" from Ord (all ordered things, in effect) provides a
'compare' function that returns EQ, LT or GT. You then "switch" on the
result. (Scare quotes because Haskell names everything differently.)

Given that C's comparisons (struggling to get topical again) already
produce ints, it would not have seemed odd to have provided, say, <>

that yields -1, 0 or 1 in the expected way.

Such a compare could equally usefully provide an 8-way result: 3 bits that
represent (LT,EQ,GT), giving a value 000B to 111B. With the 3-way scheme,
you can't then feed the result to a switch that wants to deal with LT and
LE, for example, in separate branches.

Not-equal is also badly defined in the 3-way result (either -1 or 1), but is
101B in the 8-way one.

And if you needed to encode the desired comparison itself, to send to a
function for example, then the 8-way code allows you to represent all six
comparisons (000B and 111B are no-ops), instead of just three.
 
B

Ben Bacarisse

BartC said:
Such a compare could equally usefully provide an 8-way result: 3 bits
that represent (LT,EQ,GT), giving a value 000B to 111B. With the 3-way
scheme, you can't then feed the result to a switch that wants to deal
with LT and LE, for example, in separate branches.

Not-equal is also badly defined in the 3-way result (either -1 or 1),
but is 101B in the 8-way one.

And if you needed to encode the desired comparison itself, to send to
a function for example, then the 8-way code allows you to represent
all six comparisons (000B and 111B are no-ops), instead of just three.

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.
 
8

88888 Dihedral

I, the op, hereby grant dispensation to all persons

in this thread to get as far off-topic as they like.

Well, for an ordered set with comparison operations,

I'll use non-zero, less than for the signed , and smaller
for the unsigned, and just test whether the compiler is
stupid or smart to chunk out results with some goto, i.e. jump
in the final instructions.
 

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

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top