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

Storage of char in 64 bit machine

P: n/a
Hi all,

I have a simple definitioin in a C file something like this.

main()
{
char a;
.......
int k;
}

Since character is 8 bit, how is it stored in the machine in a 64 bit
machine. If it is word aligned, what about the rest of the bytes. What
about the retrievel of the char c, will it be expensive. Is it
expensive w.r.t read or write.

Thanx and Regards,
Aruna

Aug 14 '06 #1
Share this Question
Share on Google+
74 Replies


P: n/a
ar**********@gmail.com wrote:
Hi all,

I have a simple definitioin in a C file something like this.

main()
{
char a;
.......
int k;
}

Since character is 8 bit, how is it stored in the machine in a 64 bit
machine.
That's up to the compiler, and it depends what you mean by "a 64 bit
machine".
If it is word aligned, what about the rest of the bytes.
What about the rest of what bytes?
What about the retrievel of the char c, will it be expensive.
That depends on the compiler. I wouldn't /expect/ it to be expensive.
`c` might well be stored in a register, for example [1].
Is it expensive w.r.t read or write.
That depends.

Have you a problem for which this would be an explanation?

(Ignoring your `...`s, the compiler could arrange that `main` above
is implemented with no local variables at all ...)

--
Chris "seeker" Dollin
"Reaching out for mirrors hidden in the web." - Renaissance, /Running Hard/

Aug 14 '06 #2

P: n/a

ar**********@gmail.com wrote:
Hi all,

I have a simple definitioin in a C file something like this.

main()
{
char a;
.......
int k;
}

Since character is 8 bit,
Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.
how is it stored in the machine in a 64 bit
machine. If it is word aligned, what about the rest of the bytes. What
about the retrievel of the char c, will it be expensive. Is it
expensive w.r.t read or write.
Storage and alignment are the concerns of the compiler and the
"execution platform". It /could/ be that this compiler does as you
suspect, and uses 8 bits out of 64 to store a char entity, leaving the
remaining bits unused and unusable.

Alternatively, the compiler /may/ reorganize your allocations (at any
one level) such that all the small entities are grouped together in
storage, permitting other char values to occupy the "slack" space from
your allocation of "char a;".

This is entirely up to the implementation of the compiler; AFAICR, the
C standard doesn't require any specific behaviour in this regard. If
the compiler's code organization and optimization are a problem for
you, you'll either have to switch compilers or change your code to live
more optimally within the restrictions that the compiler places on you.
Thanx and Regards,
Aruna
You're welcome
--
Lew Pitcher

Aug 14 '06 #3

P: n/a
In article <11**********************@b28g2000cwb.googlegroups .com>,
Lew Pitcher <lp******@sympatico.cawrote:
>Alternatively, the compiler /may/ reorganize your allocations (at any
one level) such that all the small entities are grouped together in
storage, permitting other char values to occupy the "slack" space from
your allocation of "char a;".
>This is entirely up to the implementation of the compiler; AFAICR, the
C standard doesn't require any specific behaviour in this regard.
I'm not sure what you mean by "at any one level".

Note that compilers are not permitted to reorder fields in a struct,
only to put padding between the fields. (I would tend to think
that fields of any one struct are all at the same "level", provided
they are not aggregate types.)
--
Programming is what happens while you're busy making other plans.
Aug 14 '06 #4

P: n/a

Walter Roberson wrote:
In article <11**********************@b28g2000cwb.googlegroups .com>,
Lew Pitcher <lp******@sympatico.cawrote:
Alternatively, the compiler /may/ reorganize your allocations (at any
one level) such that all the small entities are grouped together in
storage, permitting other char values to occupy the "slack" space from
your allocation of "char a;".
This is entirely up to the implementation of the compiler; AFAICR, the
C standard doesn't require any specific behaviour in this regard.

I'm not sure what you mean by "at any one level".
I wasn't too clear there, so let me elaborate

Assume the code fragment...

{
/* "level" A */
char aa; int ab, ac;
char ad;

{
/* "level" B */
char ae;

}
}

In the nesting level I've called "A", the compiler /may/ optimize the
allocations of aa, ab, ac, and ad so that aa and ad are adjacent in
"memory". For the OP's example of 8-bit char data items and 64bit
wordsizes, this could mean that 16bits of one 64bit word is occupied by
2 independant char data items, wasting only 48 bits of hidden padding
(assuming that the compiler word-aligns each allocation). The OPs
scenario would have each char data item (aa and ad) possible occupy 8
bits of unique 64bit words, leaving 112 bits (2 x 56) unused.

However, because variable ae is declared within a different "level" of
the code, I doubt that most compilers would "optimize" its allocation
to occupy another 8 bits within that 64bit allocation that aa and ad
potentially occupy.

That's what I meant by "at any one level"
Note that compilers are not permitted to reorder fields in a struct,
only to put padding between the fields. (I would tend to think
that fields of any one struct are all at the same "level", provided
they are not aggregate types.)
Up to this point, structure (and union) allocations haven't been part
of the discussion. Your point is taken; the compiler isn't permitted to
reorder fields within a structure, even in order to take advantage of
the potential space savings that such a reorganization might offer.

--
Lew Pitcher

Aug 14 '06 #5

P: n/a
Lew Pitcher wrote:
Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.
So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;

int
CurEqual(xCUR *c1, xCUR *c2)
{
if (c1->iCUR == c2->iCUR)
printf("Same currency %s\n", c1->acCUR);
else
printf("%s and %s are different\n",
c1->acCUR, c2->acCUR);
}

Having to call a strcmp() in such cases seems like a bad waste to me, but I
don't see, how the compiler could possibly optimize such a code without the
trick above...

-mi
Aug 14 '06 #6

P: n/a
In article <1953472.hIqUUy82Sv@misha>,
Mikhail Teterin <us****@aldan.algebra.comwrote:
>Lew Pitcher wrote:
>Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.
>So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?
typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;
Note that int32_t is not certain to exist at all. There is an
int_least32_t that is certain to be at least 32 bits, and that will
exist on all C99 platforms.

sizeof int32_t will tell you how many "bytes" int32_t requires, and
by definition each char is exactly one byte long. However, it should
not be assumed that int32_t and char acCUR[sizeof int32_t] both
offer the same number of bits of "useable" storage, as the signed
int types are permitted to have internal non-value bits. When
you are trying to do type-punning via unions, you should use
unsigned char to be sure to be able to access all bits (including
the ones that the other fields might happen to treat as non-value bits.)
--
All is vanity. -- Ecclesiastes
Aug 14 '06 #7

P: n/a

Mikhail Teterin wrote:
Lew Pitcher wrote:
Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.

So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;
Not portably, no.

int32_t isn't guaranteed to exist in every compliant compilation system

CHAR_BITS isn't guaranteed to be equal to 8 in every compliant
compilation system

char acCUR[4]; isn't guaranteed to contain 32 bits in every compliant
compilation system

Aug 14 '06 #8

P: n/a
Mikhail Teterin wrote:
Lew Pitcher wrote:
>Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.

So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;

int
CurEqual(xCUR *c1, xCUR *c2)
{
if (c1->iCUR == c2->iCUR)
printf("Same currency %s\n", c1->acCUR);
else
printf("%s and %s are different\n",
c1->acCUR, c2->acCUR);
}
It definitely cannot. Apart from the fact that int could be only 16 bits
it could also have a trap representation, or two representations of the
same value (+0 and -0).
Having to call a strcmp() in such cases seems like a bad waste to me, but I
don't see, how the compiler could possibly optimize such a code without the
trick above...
It could optimise it very easily using strcmp (inline the function and
then optimise it in place with the rest of the code). Potentially it
could be *more* efficient since it might compare fewer bytes.

If you think something like that is an optimisation worth considering
then you should not attempt *any* optimisation since at best you are
likely to have no effect or make it slower, but you are just as likely
to break it. Write code to be simple and understandable and let the
optimisation phase of the compiler do its job, it's probably a lot
better at it than you.
--
Flash Gordon
Still sigless on this computer.
Aug 14 '06 #9

P: n/a


Mikhail Teterin wrote On 08/14/06 13:50,:
Lew Pitcher wrote:

>>Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.


So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;

int
CurEqual(xCUR *c1, xCUR *c2)
{
if (c1->iCUR == c2->iCUR)
printf("Same currency %s\n", c1->acCUR);
else
printf("%s and %s are different\n",
c1->acCUR, c2->acCUR);
}

Having to call a strcmp() in such cases seems like a bad waste to me, but I
don't see, how the compiler could possibly optimize such a code without the
trick above...
The trick will work on many machines, but you're right:
it works "by chance, not by design."

But is the loss worth weeping over? Consider: You've
saved a strcmp() of two short strings, but at what cost?
If your currency codes are "naturally" strings, you've now
got to bundle them up into xCUR unions; you must actually
copy the string characters into the acCUR members. This
uglifies your code -- and avoiding a strcmp() at the cost
of two calls to strcpy() doesn't seem like a step in the
right direction!

If you're making "a lot" of these comparisons, it might
make more sense to convert the strings to numeric codes at
the point when they're read in or whatever. You're probably
going to validate the strings by looking them up in a table
of "known" currency codes or some such, right? Having done
the lookup, it's pretty easy to get the table to provide an
easily-manipulated numeric code that can be used elsewhere in
the program; you'd just deal with strings "on the periphery."
That'd be cleaner, probably faster, and certainly more portable.

--
Er*********@sun.com

Aug 14 '06 #10

P: n/a
Eric Sosman wrote:
If you're making "a lot" of these comparisons, it might
make more sense to convert the strings to numeric codes at
the point when they're read in or whatever.
Yes, this is an alternative... But being able to access them as strings at
the same time (such as for printing) remains desirable.
You're probably going to validate the strings by looking them up in a
table of "known" currency codes or some such, right? šHaving done
the lookup, it's pretty easy to get the table to provide an
easily-manipulated numeric code that can be used elsewhere in
the program; you'd just deal with strings "on the periphery."
The strings come from database, actually, and have to be memcpy-ied once
anyway. Treating them as 4-byte integers would be a nice convenience not
only for comparisions (of which the code does a lot indeed), but also for
future assignments (`trade1.cur.iCur = trade2.cur.iCur' vs.
`strcpy(trade1.cur, trade2.cur)').

Keeping an internal table of numbers vs. strings is rather inconvenient when
debugging (can't just look at the string), and also wasteful -- the four
bytes is already an overkill (2^32 possible currencies, when the maximum is
really under a thousand)...

As so often happens, the really cool things C can do are "not supported" and
frowned upon by the authoritatively-sounding gurus...

Thanks,

-mi
Aug 14 '06 #11

P: n/a
"Mikhail Teterin" <us****@aldan.algebra.comwrote in message
news:1953472.hIqUUy82Sv@misha...
Lew Pitcher wrote:
>Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.

So, comparing, say, 4-char arrays (like currency codes) can NOT be
done in the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;
....
Having to call a strcmp() in such cases seems like a bad waste to me,
but I don't see, how the compiler could possibly optimize such a code
without the trick above...
That'll work on most modern systems, but it's not portable and it won't work
everywhere. Use strcmp(); that's guaranteed to work.

The implementation is likely to have a very, very clever strcmp() that will
perform at least as well as your code (possibly doing the same thing
internally, if it's known to be safe) and likely even better if the compiler
is reasonably modern due special knowledge and treatment of common
functions/idioms.

Remember, premature optimization is the root of all evil. Avoid the
temptation until profiling shows the clear, less "clever" option isn't fast
enough -- and then consider using a better algorithm, if possible, before
using unportable code.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking

--
Posted via a free Usenet account from http://www.teranews.com

Aug 14 '06 #12

P: n/a
Flash Gordon wrote:
Mikhail Teterin wrote:
>Lew Pitcher wrote:
>>Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.

So, comparing, say, 4-char arrays (like currency codes) can NOT be
done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;
<snip>
It definitely cannot. Apart from the fact that int could be only 16 bits
<snip>

Oops. I missed that it was int32_t! Obviously that will be 32 bits if it
exists, but it might not exist.

My comments about optimisation stand though. Don't do it. Experts only
consider micro-optimisation if they *know* they have a problem,
otherwise they write the code to be understandable.
--
Flash Gordon
Still sigless on this computer.
Aug 14 '06 #13

P: n/a


Mikhail Teterin wrote On 08/14/06 15:34,:
Eric Sosman wrote:
>>If you're making "a lot" of these comparisons, it might
make more sense to convert the strings to numeric codes at
the point when they're read in or whatever.


Yes, this is an alternative... But being able to access them as strings at
the same time (such as for printing) remains desirable.
printf ("Currency = %s\n" CurrencyName[index]);

or maybe

printf ("Currency = %s\n", Currency[index].name);
>>You're probably going to validate the strings by looking them up in a
table of "known" currency codes or some such, right? Having done
the lookup, it's pretty easy to get the table to provide an
easily-manipulated numeric code that can be used elsewhere in
the program; you'd just deal with strings "on the periphery."


The strings come from database, actually, and have to be memcpy-ied once
anyway. Treating them as 4-byte integers would be a nice convenience not
only for comparisions (of which the code does a lot indeed), but also for
future assignments (`trade1.cur.iCur = trade2.cur.iCur' vs.
`strcpy(trade1.cur, trade2.cur)').

Keeping an internal table of numbers vs. strings is rather inconvenient when
debugging (can't just look at the string), and also wasteful -- the four
bytes is already an overkill (2^32 possible currencies, when the maximum is
really under a thousand)...
I think that simply adds support to my suggestion: Instead of
maintaining a lot of four-byte strings, you could be storing a lot of
two-byte (probably) `short' table indices.
As so often happens, the really cool things C can do are "not supported" and
frowned upon by the authoritatively-sounding gurus...
Yeah, well. One might equally opine that only the spoiled rotten
button-clicking GUI-besotted drooling whining spaced-out brainless --
oh, sorry, didn't mean to offend -- um, only "a few extraordinary
people" consider such trickery "really cool."

--
Er*********@sun.com

Aug 14 '06 #14

P: n/a
"Lew Pitcher" <lp******@sympatico.cawrites:
Walter Roberson wrote:
>In article <11**********************@b28g2000cwb.googlegroups .com>,
Lew Pitcher <lp******@sympatico.cawrote:
>Alternatively, the compiler /may/ reorganize your allocations (at any
one level) such that all the small entities are grouped together in
storage, permitting other char values to occupy the "slack" space from
your allocation of "char a;".
>This is entirely up to the implementation of the compiler; AFAICR, the
C standard doesn't require any specific behaviour in this regard.

I'm not sure what you mean by "at any one level".

I wasn't too clear there, so let me elaborate

Assume the code fragment...

{
/* "level" A */
char aa; int ab, ac;
char ad;

{
/* "level" B */
char ae;

}
}

In the nesting level I've called "A", the compiler /may/ optimize the
allocations of aa, ab, ac, and ad so that aa and ad are adjacent in
"memory". For the OP's example of 8-bit char data items and 64bit
wordsizes, this could mean that 16bits of one 64bit word is occupied by
2 independant char data items, wasting only 48 bits of hidden padding
(assuming that the compiler word-aligns each allocation). The OPs
scenario would have each char data item (aa and ad) possible occupy 8
bits of unique 64bit words, leaving 112 bits (2 x 56) unused.

However, because variable ae is declared within a different "level" of
the code, I doubt that most compilers would "optimize" its allocation
to occupy another 8 bits within that 64bit allocation that aa and ad
potentially occupy.

That's what I meant by "at any one level"
There are several possible strategies for allocating objects in nested
and/or parallel blocks. For example:

void foo(void)
{
int outer;
{
int inner1;
}
{
int inner2a;
int inner2b;
}
}

A simple-minded compiler might allocate space for all 4 objects on
entry to the function.

Or the compiler might recognize that the two inner scopes cannot be
active at the same time, and overlap their allocations, but still
allocate everything on function entry (requiring space for 3 ints).

Or the compiler might allocate space for each block's local objects
only on entry to the block, and deallocate it on leaving the block.
In this case, the compiler (actually the generated code) would
allocate space for one int on entry to foo().

A compiler following the first or second strategy can freely rearrange
the allocated objects to minimize gaps, even across block boundaries.

--
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.
Aug 14 '06 #15

P: n/a
Mikhail Teterin <us****@aldan.algebra.comwrites:
Lew Pitcher wrote:
>Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.

So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;

int
CurEqual(xCUR *c1, xCUR *c2)
{
if (c1->iCUR == c2->iCUR)
printf("Same currency %s\n", c1->acCUR);
else
printf("%s and %s are different\n",
c1->acCUR, c2->acCUR);
}

Having to call a strcmp() in such cases seems like a bad waste to me, but I
don't see, how the compiler could possibly optimize such a code without the
trick above...
Even if all your assumptions are valid, strcmp() doesn't do the same
thing as your int32_t comparison. Comparing two int32_t values
compares all the bits; strcmp() only compares up to the '\0' that
terminates each string.

For example, you could have c1->acCUR equal to
{ 'X', 'Y', '\0', 'A' }
and c2->acCUR equal to
{ 'X', 'Y', '\0', 'B' }
Not all the corresponding array elements are equal, but strcmp() will
ignore the 'A' and 'B' characters.

--
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.
Aug 14 '06 #16

P: n/a
Eric Sosman wrote:
Yeah, well. šOne might equally opine that only the spoiled rotten
button-clicking GUI-besotted drooling whining spaced-out brainless --
oh, sorry, didn't mean to offend -- um, only "a few extraordinary
people" consider such trickery "really cool."
Give me an example, of trickery, that YOU consider really cool, that is also
portable...

-mi
Aug 15 '06 #17

P: n/a
Keith Thompson wrote:
For example, you could have c1->acCUR equal to
{ 'X', 'Y', '\0', 'A' }
and c2->acCUR equal to
{ 'X', 'Y', '\0', 'B' }
Not all the corresponding array elements are equal, but strcmp() will
ignore the 'A' and 'B' characters.
I know. Currencies, however, are all 3-character strings (plus the
terminating '\0'). Thus they are perfectly suited to be treated as int32_t,
when convenient.

That it is not 100% portable is already rammed into me by the friendly folks
on this board. I'd like to know an example of the actual hardware/compiler
combo, where it would not work, though...

Thanks,

-mi
Aug 15 '06 #18

P: n/a
Mikhail Teterin wrote:
Eric Sosman wrote:

>>Yeah, well. One might equally opine that only the spoiled rotten
button-clicking GUI-besotted drooling whining spaced-out brainless --
oh, sorry, didn't mean to offend -- um, only "a few extraordinary
people" consider such trickery "really cool."


Give me an example, of trickery, that YOU consider really cool, that is also
portable...
Straying from topicality, hence the change in Subject ...

Once upon a time, in my rambunctious youth, I would have had
no trouble answering your question. It was cool to use `x&(x-1)'
to zero the lowest-order one-bit, it was cool to use "horizontal
addition" to count the one-bits or compute parity, it was cool to
use `POP PC' instead of `RETURN' (yes! it was faster!), it was
cool to use a computed GOTO instead of an IF (as you may deduce,
my R.Y. was some time ago ...)

But a funny thing happened: Progress.

The first computer I used had forty thousand decimal digits
of memory, of which one hundred locations were reserved for the
table that allowed it to add and subtract integers. All other
arithmetic -- integer multiplication and division, all kinds of
floating-point -- were done via subroutines. I no longer recall
the instruction timings for that machine, but I do remember that
when it was replaced by a newer system that could execute some
kinds of instructions in LESS THAN TWO MICROSECONDS it seemed
like an onrush of unthinkable speed.

On that machine, in my R.Y., "cool tricks" were a necessity,
a staple of daily existence. They were the difference between
a program that ran and a program that failed (sorry: your code
is twenty digits bigger than memory). Moving a few instructions
out of an inner loop was a big deal -- and the compilers of the
day were not very good at such things. After all, they had only
the resources of the same slow small machine at their disposal,
and were already stressed simply to get the translations done.
(It was not unusual for a compiler to be a program of five or
so sequential "passes" communicating intermediate results via
temporary files, sometimes on reels of magnetic tape or even on
decks of punched cards.) In my R.Y. the compilers needed all the
help we could give them.

Ah, but there's been Progress.

Not quite twenty years ago I bought my first x386 machine,
and it wasn't long before I had a sort of magical realization:
My very modest 640x480 display was being driven by a bare-bones
low-end video card with SIXTEEN TIMES THE MEMORY CAPACITY OF MY
ENTIRE COLLEGE CAMPUS! In a PERIPHERAL, for Crissakes!

It sort of brought home to me the degree to which progress
had changed my world -- and the sobering fact that the cool tricks
I once employed to squeeze three more instructions into the size
of one disk sector were simply no longer relevant. The economic
facts that once ruled my profession no longer held; a different
dynamic was loose in the world.

The world's finest maker of buggy whips goes to the poorhouse
when the automobile comes along. The careful choice of leathers
for different parts of the whip, the judicious use of oak for
stiffness and ash for springiness that gives the handle its
inimitable feel, the consummate craftsmanship in the double-looped
stitching to prevent water and snow from penetrating and rotting
the interior ... Irrelevant. Useless. Outmoded. Inane.

As one can admire the skills of the buggy whip makers and the
inordinate amount of labor they would expend on a single whip, so
one can admire the "cool tricks" of the programmer-craftsmen and
their perseverance at desk-checking to avoid messing up even one
of their couple of compiles per day. (I remember once poring over
a core dump trying to see whether a failed program had at least
computed the right intermediate results before dying, doing pencil-
and-paper long division IN HEXADECIMAL to check the results.) As
I say, one can admire the ingenuity, cleverness, sneakiness, and
sweat -- but the proper venue for such admiration is the same as
for admiring buggy whips: In a museum of antiquities, not in code
written for the present day.

Can you make a fire by rubbing two sticks together? It's
doable -- I've seen it done -- but do you feel any less "able"
if you cannot do it yourself?

Do you know how to flake flint to make a knife edge? If not,
do you find your daily life impeded by the loss of that cool trick?

What kind of sapling will make a good bow? What animal's
entrails will you wind to make a good bowstring, and how do you
get them out of the carcase intact, and how do you prevent them
from rotting -- how, for that matter, do you catch and kill the
animal?

All these once-essential skills are now become irrelevant.
Interesting to antiquarians, perhaps, and in that limited sense
still cool -- but of no serious consequence any more. You could
be the world's greatest fire-maker, the best flint-flaker ever
to "Ouch!" his thumb, and the best bowyer who ever bent birch,
and you would be ... what? Not chatting on Usenet, I imagine.

I have (figuratively) lived in caves and eaten tasty nematodes
scrabbled from the dirt (there's a trick to finding the good ones,
I'll show ya how it's done). Nowadays I live in a house and get my
food from a supermarket -- and y'know? I really don't miss the
nematodes all that much.

And *that's* cool.

--
Eric Sosman
es*****@acm-dot-org.invalid
Aug 15 '06 #19

P: n/a
On Mon, 14 Aug 2006 22:41:38 -0400, Mikhail Teterin
<us****@aldan.algebra.comwrote in comp.lang.c:
Keith Thompson wrote:
For example, you could have c1->acCUR equal to
{ 'X', 'Y', '\0', 'A' }
and c2->acCUR equal to
{ 'X', 'Y', '\0', 'B' }
Not all the corresponding array elements are equal, but strcmp() will
ignore the 'A' and 'B' characters.

I know. Currencies, however, are all 3-character strings (plus the
terminating '\0'). Thus they are perfectly suited to be treated as int32_t,
when convenient.

That it is not 100% portable is already rammed into me by the friendly folks
on this board. I'd like to know an example of the actual hardware/compiler
combo, where it would not work, though...

Thanks,

-mi
Almost every single DSP in existence, for starters.

I routinely work on a TI DSP these days where CHAR_BIT is 16 and
sizeof(int) is 1.

So your union of one int (and unsigned int would be better for type
punning) and an array of four chars would be four bytes long, and
comparing the int member of two unions would only compare the first
character of the array in each.

Even if you have a <stdint.h>, which TI's compiler did not provide but
I did (for the types actually supported), and have int32_t typedef'ed
to signed long (and unit32_t typedef'ed to unsigned long), the size of
the (un)signed long at the beginning of union is only two bytes.

There are some 32 bit DSPs where all of char, short, int, and long
have 32 bits.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Aug 15 '06 #20

P: n/a
Jack Klein wrote:
Almost every single DSP in existence, for starters.
When a concept of "currency" becomes applicable to a DSP, I may accept this
example... I was, of course, talking about general-purpose computers...
I routinely work on a TI DSP these days where CHAR_BIT is 16 and
sizeof(int) is 1.
This is interesting -- why is this a char, and not, say, a short then? Is
there an 8-bit type at all?

-mi
Aug 16 '06 #21

P: n/a
Eric Sosman wrote:
As one can admire the skills of the buggy whip makers and the
inordinate amount of labor they would expend on a single whip, so
one can admire the "cool tricks" of the programmer-craftsmen and
their perseverance
The major difference between the relationship of a buggy whip maker and a
car vs. that of an old-time programmer and a modern computer -- the
difference that pretty much destroys your entire analogy -- is that a car
will not run any faster, when whipped.

A well-crafted program, however, _will_ run faster on a modern computer.

The vast speed and memory-amounts improvements of modern computers are
supposed to enable them to run programs better -- not to allow the
programmers to be sloppier.

I'm not pushing *you* to write as efficient programs as you did, when
you "lived in the cage". But don't stop *me* from trying to keep my
programs runnable on that ancient hardware -- even if they'll never see it.

Running on a DSP (where CHAR_BITS is 16) is not a valid argument. The only
sound one s that a compiler can do a better job. But I doubt, it can --
I'll verify and post the results...

Yours,

-mi
Aug 16 '06 #22

P: n/a
Mikhail Teterin posted:
>I routinely work on a TI DSP these days where CHAR_BIT is 16 and
sizeof(int) is 1.

This is interesting -- why is this a char, and not, say, a short then? Is
there an 8-bit type at all?

Define "8-Bit type". Do you mean 8 object representation bits, or 8 value
representation bits?

If you mean object representation bits, then there can't be (unless there's a
type which is provided as an extension).

If CHAR_BIT is 16, then all of the three "char" types must have 16 object
representation bits.

--

Frederick Gotham
Aug 16 '06 #23

P: n/a
Stephen Sprunk wrote:
The implementation is likely to have a very, very clever strcmp() that
will perform at least as well as your code (possibly doing the same thing
internally, if it's known to be safe) and likely even better if the
compiler is reasonably modern due special knowledge and treatment of
common functions/idioms.
Well, here are some benchmarks comparing the use of strcmp() to compare
short character strings (4 characters).

FreeBSD6.1/i386 using `gcc version 3.4.4 [FreeBSD] 20050518'
with "-pedantic -Wall -O5 -pipe -march=pentium4 -DNDEBUG -DNODEBUG
-fomit-frame-pointer":

./bench 100000000
str: used 1119486 microseconds
int: used 406449 microseconds

FreeBSD6.1/amd64 using the same compiler as above
with "-pedantic -Wall -O5 -pipe -march=opteron -DNDEBUG -DNODEBUG
-fomit-frame-pointer":

obj.amd64/bench 100000000
str: used 1403187 microseconds
int: used 392897 microseconds

AIX5.2/powerpc using IBM's cc with cc -O3 (-O4 would not link):

./aix-bench 100000000
str: used 3240000 microseconds
int: used 630000 microseconds

Solaris8/sparc using Sun's 6u2 compiler with `-v -fast' (fast is the "macro"
option turning on all possible optimizations including Sun's own libmil):

./sun4u-bench 100000000
str: used 7020000 microseconds
int: used 1300000 microseconds

the same using 64-bit binaries (-v -fast -xarch=v9b):

str: used 7920000 microseconds
int: used 1470000 microseconds

Solaris10/opteron using Sun's `cc: Sun C 5.7 2005/01/07' compiler with
`-fast -xarch=amd64':

./sunx86-bench 100000000
str: used 962088 microseconds
int: used 319509 microseconds

Of the above, the Sun's cc/libmil is definitely has the special "knowledge
and treatment of common functions/idioms" such as strcmp(), but even there
using strcmp() was 5 times slower...

It seems, that for the limited cases like this -- when the strings are of
the same length and fit nicely into an integer type -- treating them as such
is hugely beneficial. And, contrary to authoritative assertions posted in
this thread, compiler is NOT able to detect such cases.

I'm attaching (sigh) the simple-minded C-code to this posting -- please,
poke at it and/or reproduce my results... It even allows for CHAR_BIT to be
16 :-)

Thanks!

-mi
Aug 16 '06 #24

P: n/a
Frederick Gotham posted:

If CHAR_BIT is 16, then all of the three "char" types must have 16
object representation bits.

Just to clarify:

It's possible to have a 16-Bit unsigned char and unsigned short, and yet have
an 8-bit signed char (which would contain 8 bits of padding).

--

Frederick Gotham
Aug 16 '06 #25

P: n/a
Frederick Gotham wrote:
It's possible to have a 16-Bit unsigned char and unsigned short, and yet
have an 8-bit signed char (which would contain 8 bits of padding).
But strcmp() expects "char *", so unsigned chars are not of concern for my
example, right?

-mi
Aug 16 '06 #26

P: n/a
Mikhail Teterin <us****@aldan.algebra.comwrites:
[snip]
I'm attaching (sigh) the simple-minded C-code to this posting -- please,
poke at it and/or reproduce my results... It even allows for CHAR_BIT to be
16 :-)
Didn't we just go over this? Is there some reason you couldn't have
posted the C code as part of your article?

--
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.
Aug 16 '06 #27

P: n/a
Mikhail Teterin posted:
Frederick Gotham wrote:
>It's possible to have a 16-Bit unsigned char and unsigned short, and yet
have an 8-bit signed char (which would contain 8 bits of padding).

But strcmp() expects "char *", so unsigned chars are not of concern for my
example, right?

Sorry, I haven't looked at your example -- I just jumped into the thread when
I saw mention of the technicalities of integer types... like a bee to honey!
;)

--

Frederick Gotham
Aug 16 '06 #28

P: n/a
Keith Thompson wrote:
Didn't we just go over this? Is there some reason you couldn't have
posted the C code as part of your article?
We did. And I ended up convinced, that only inertia (and the desire to force
a newcomer to obey the rules of the club), are what makes this an issue in
the first place.

People with news-readers, that are not MIME-aware will just see these
textual attachments as part of the article.

MIME-aware news-readers will be able to handle them better this way...

Sorry, if it were one file, I would've inlined it, but three -- that's just
too much trouble.

-mi
Aug 16 '06 #29

P: n/a
Mikhail Teterin <us****@aldan.algebra.comwrites:
Frederick Gotham wrote:
>It's possible to have a 16-Bit unsigned char and unsigned short, and yet
have an 8-bit signed char (which would contain 8 bits of padding).

But strcmp() expects "char *", so unsigned chars are not of concern for my
example, right?
I haven't looked at your example lately, but strcmp() in effect works
with unsigned chars. Its declaration makes it look like it deals
with plain chars:

int strcmp(const char *s1, const char *s2);

but:

The sign of a nonzero value returned by the comparison functions
memcmp, strcmp, and strncmp is determined by the sign of the
difference between the values of the first pair of characters
(both interpreted as unsigned char) that differ in the objects
being compared.

--
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.
Aug 16 '06 #30

P: n/a
Mikhail Teterin <us****@aldan.algebra.comwrites:
Keith Thompson wrote:
>Didn't we just go over this? Is there some reason you couldn't have
posted the C code as part of your article?

We did. And I ended up convinced, that only inertia (and the desire to force
a newcomer to obey the rules of the club), are what makes this an issue in
the first place.

People with news-readers, that are not MIME-aware will just see these
textual attachments as part of the article.

MIME-aware news-readers will be able to handle them better this way...

Sorry, if it were one file, I would've inlined it, but three -- that's just
too much trouble.
Then you reached the wrong conclusion.

I, for one, will ignore any attachments posted to this newsgroup. I
will consider changing this policy only if there's a general consensus
among the regulars that text-only attachments are acceptable. (I'm
not claiming that this is a policy of the newsgroup; I speak only for
myself.)

--
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.
Aug 16 '06 #31

P: n/a
Keith Thompson wrote:
I, for one, will ignore any attachments posted to this newsgroup.
I have not spent much time on this group, but, so far, I have not seen
anything that would make me truly saddened by your decision...
I will consider changing this policy only if there's a general consensus
among the regulars that text-only attachments are acceptable.
You are confirming my impression, that the actual merits of text-only
attachments are secondary (or even fully irrelevant) to your decision, with
the annoyance over my violating the unwritten and unofficial "rules of the
club" being the primary...

-mi
Aug 16 '06 #32

P: n/a
Keith Thompson wrote:
Mikhail Teterin <us****@aldan.algebra.comwrites:
>>Keith Thompson wrote:
>>>Didn't we just go over this? Is there some reason you couldn't have
posted the C code as part of your article?

We did. And I ended up convinced, that only inertia (and the desire to force
a newcomer to obey the rules of the club), are what makes this an issue in
the first place.

People with news-readers, that are not MIME-aware will just see these
textual attachments as part of the article.

MIME-aware news-readers will be able to handle them better this way...

Sorry, if it were one file, I would've inlined it, but three -- that's just
too much trouble.


Then you reached the wrong conclusion.

I, for one, will ignore any attachments posted to this newsgroup. I
will consider changing this policy only if there's a general consensus
among the regulars that text-only attachments are acceptable. (I'm
not claiming that this is a policy of the newsgroup; I speak only for
myself.)
In this case, I found the attachments handy, just a quick 'save all' in
Mozilla, rather than several copy and pastes.

For a single file, inline is probably best, but for several attachments
can help

--
Ian Collins.
Aug 17 '06 #33

P: n/a
On Wed, 16 Aug 2006 20:03:57 -0400, Mikhail Teterin
<us****@aldan.algebra.comwrote:
>Keith Thompson wrote:
>I, for one, will ignore any attachments posted to this newsgroup.

I have not spent much time on this group, but, so far, I have not seen
anything that would make me truly saddened by your decision...
>I will consider changing this policy only if there's a general consensus
among the regulars that text-only attachments are acceptable.

You are confirming my impression, that the actual merits of text-only
attachments are secondary (or even fully irrelevant) to your decision, with
the annoyance over my violating the unwritten and unofficial "rules of the
club" being the primary...
Actually, I think the annoyance comes from your continuing to argue
about it after being informed about the "unwritten and unofficial
rules of the club". The "club", incidentally, includes very many
usenet groups. As it says in http://www.netmeister.org/news/usenet/
after mentioning that many users still use dialup:

"Let this be just one reason why you should never ever post an
attachment into a newsgroup that does not specifically state in its
Charta that it is desired. Usually, attachments are only appropriate
in *binaries*-newsgroups."

--
Al Balmer
Sun City, AZ
Aug 17 '06 #34

P: n/a
Mikhail Teterin wrote:
Lew Pitcher wrote:
Actually, a character isn't 8 bit. I'm simplifying a bit, but a
character is guaranteed to be /at least/ 8 bits wide, and is permitted
to be as wide as necessary. For all we (or you) know, a char might be
64bits wide on your platform.

So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;

int
CurEqual(xCUR *c1, xCUR *c2)
{
if (c1->iCUR == c2->iCUR)
printf("Same currency %s\n", c1->acCUR);
else
printf("%s and %s are different\n",
c1->acCUR, c2->acCUR);
}

Having to call a strcmp() in such cases seems like a bad waste to me, but I
don't see, how the compiler could possibly optimize such a code without the
trick above...
The compiler cannot do that optimization because its not correct.
strcmp() stops executing its inner loop once it reads a '\0'. I.e.,
its possible for the strcmp()'s to be equal where the int32_t's are not
equal. Also the compiler is allowed to align struct entries as they
like. So on a 64 bit big endian system, the int32_t might not
intersect with any of the 4 acCur[] characters.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Aug 17 '06 #35

P: n/a
Mikhail Teterin wrote:
[...]
A well-crafted program, however, _will_ run faster on a modern computer.
Good. Splendid. But: HOW MUCH faster?

Elsethread you have posted an attempt to quantify HOW MUCH,
and your results suggest that the particular "cool" trick you
favor will save ...

0.00000000713037 seconds per comparison.

(Frankly, I doubt that the measurement accuracy justifies the
number of "significant" digits you've reported, but let that
pass: 0.00000000713037 seconds it is. Congratulations on your
savings; don't spend it all in one place.)

To save one second, you need to make 140245176+ comparisons.

To save the -- what? hour? let's be generous and say thirty
minutes -- to recoup the thirty minutes you have already spent
on this folly, JUST TO BREAK EVEN, you need to make 252441317912
comparisons. That number is almost fifty-nine times larger than
the largest value of an `unsigned int' on many implementations;
you will have trouble even *counting* the number of comparisons
you must make before you break even.

Thesis: A program that makes 252441317912 comparisons doesn't
need to make those comparisons faster; it needs a way to avoid
all those stupid comparisons!

Mikhail, I can see your error and understand it and sympathize
with it, because in my mis-spent youth I made the same mistake. I
claim no superiority; it's quite possible (maybe even likely) that
my sins were greater than yours are, that I exercised even worse
judgement than you are exercising now. As a sort of reformed drunk
I address the AA meeting: You are on the broad highway to Hell. You
have become besotted (as I in my time was besotted) with "clever"
tricks and "subtle" devices, and (like me) you have not stopped to
count the cost. Consider: You are giving up portability, you are
giving up clarity, you are diminishing maintainability -- and for
what? For a gain of less than one second.

Bad trade, Mikail. Very bad trade. Chortle over the cleverness
of whatever gadget takes your fancy -- but don't use it. Just don't.
You will come to regret your ingenuity -- trust me on this; I deployed
above-average ingenuity, and in the long run got into above-average
trouble. Stop, sinner, while there is yet time.

Enuf. I'm outta here.

--
Eric Sosman
es*****@acm-dot-org.invalid
Aug 17 '06 #36

P: n/a
we******@gmail.com wrote:
Mikhail Teterin wrote:
>>
So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;
[...]

Having to call a strcmp() in such cases seems like a bad waste to me, but I
don't see, how the compiler could possibly optimize such a code without the
trick above...

The compiler cannot do that optimization because its not correct.
strcmp() stops executing its inner loop once it reads a '\0'. I.e.,
its possible for the strcmp()'s to be equal where the int32_t's are not
equal. Also the compiler is allowed to align struct entries as they
like. So on a 64 bit big endian system, the int32_t might not
intersect with any of the 4 acCur[] characters.
Agree with the first part but not with the second. Look
again: it's not a struct, but a union.

--
Eric Sosman
es*****@acm-dot-org.invalid

Aug 17 '06 #37

P: n/a
Eric Sosman posted:
0.00000000713037 seconds per comparison.

7 million femtoseconds! Wow! ; )

--

Frederick Gotham
Aug 17 '06 #38

P: n/a
Keith Thompson <ks***@mib.orgwrites:
[...]
I, for one, will ignore any attachments posted to this newsgroup. I
will consider changing this policy only if there's a general consensus
among the regulars that text-only attachments are acceptable. (I'm
not claiming that this is a policy of the newsgroup; I speak only for
myself.)
I believe I was too hasty in making this statement. I've started a
new thread to discuss this issue.

--
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.
Aug 17 '06 #39

P: n/a
Mikhail Teterin wrote:
Keith Thompson wrote:
For example, you could have c1->acCUR equal to
{ 'X', 'Y', '\0', 'A' }
and c2->acCUR equal to
{ 'X', 'Y', '\0', 'B' }
Not all the corresponding array elements are equal, but strcmp() will
ignore the 'A' and 'B' characters.

I know. Currencies, however, are all 3-character strings (plus the
terminating '\0'). Thus they are perfectly suited to be treated as int32_t,
when convenient.
If that is true, then in fact this is a useful performance boost, but
its platform specific. Personally, I would just capture it like this:
*((int32_t *) &currency) rather than bothering with the union.
That it is not 100% portable is already rammed into me by the friendly folks
on this board. I'd like to know an example of the actual hardware/compiler
combo, where it would not work, though...
I am pretty sure there are real 64 bit systems (though likely they are
marginal) that will fail to do your trick correctly. Not AMD64, but
some old Crays or Sparc64s might in fact fail (they need to be big
Endian, and align struct/union entries to 64 bits). And obviously
those silly DSPs that don't support int32_t's would just fail to
compile your code.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Aug 17 '06 #40

P: n/a
Mikhail Teterin wrote:
Stephen Sprunk wrote:
The implementation is likely to have a very, very clever strcmp() that
will perform at least as well as your code (possibly doing the same thing
internally, if it's known to be safe) and likely even better if the
compiler is reasonably modern due special knowledge and treatment of
common functions/idioms.

Well, here are some benchmarks comparing the use of strcmp() to compare
short character strings (4 characters).
You shouldn't fall for the "strawman" argument, especially when its
clearly wrong. Obviously int32_t comparison will annihilate strcmp()
in real world code regardless of how good the compiler is. The only
chance the compiler has is to support cross-file inlining, constant
propagation, and a kind of global string analysis that just isn't going
to yeild fruitful optimizations in general. And that would be just to
try to pull even with integer comparison. If you used memcmp() instead
of strcmp(), things *might* be different.

Benching this is unnecessary. *Any* inner loop that contains a str*
function is always going to be way slower than any reasonably
reconsidered alternative. That's a rule of thumb people should just
always be aware of. In many cases, the std C library is actually
behind by actual orders of complexity. Here its slower because of the
poor not really parallizable str* function design (it ends up
pointlessly scanning for 4 '\0' characters no matter what).
[...] It seems, that for the limited cases like this -- when the strings are of
the same length and fit nicely into an integer type -- treating them as such
is hugely beneficial. And, contrary to authoritative assertions posted in
this thread, compiler is NOT able to detect such cases.
These "authorities" are overstepping their bounds. They have decided
that this is a newsgroup just about the C standard. Practical C
programming is way beyond both the scope of this newsgroup and those so
called authorities. Their brains have, over the years, become
hardwired in a very specific way -- if you ask the question "how do I
improve the performance of some C code" they will definitively answer
"you can't; C is not characterizable in terms of performance and
furthermore your efforts will always be made irrelevant because of how
good your compiler is, and besides you are premature in your attempts
to optimize". It doesn't matter *how* you ask the question, they will
always answer the question that way. So you should not take their
naysaying too seriously, they are just replaying a
keyboard/brain-macro.

The issue with your "trick" is that its not portable. But that's
typical of anything useful that most people do in the C language.
Otherwise, yes of course it will lead to an enormous performance
improvement (after all you are removing a str* from an inner loop.)

To make it portable, you probably want to try to isolate the *system*
through ifdef's. The reason is that you need to isolate *systems* that
align things on at most 32-bit boundaries. The exceptions will be
characterized by system. Then there's the whole sizeof(int32_t) issue
-- you probably just want to deal with 3 cases of 1, 2, 4 and forget
the other ones. Then, since you know that these strings are exactly 3
characters, you should use *memcmp()*, not strcmp() (its a little
faster) on the fallback cases.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Aug 17 '06 #41

P: n/a
Eric Sosman wrote:
we******@gmail.com wrote:
Mikhail Teterin wrote:
>So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;
[...]

Having to call a strcmp() in such cases seems like a bad waste to me, but I
don't see, how the compiler could possibly optimize such a code without the
trick above...
The compiler cannot do that optimization because its not correct.
strcmp() stops executing its inner loop once it reads a '\0'. I.e.,
its possible for the strcmp()'s to be equal where the int32_t's are not
equal. Also the compiler is allowed to align struct entries as they
like. So on a 64 bit big endian system, the int32_t might not
intersect with any of the 4 acCur[] characters.

Agree with the first part but not with the second. Look
again: it's not a struct, but a union.
If the system is a 64 bit one, then it might force all entries to be
aligned to 64 bit boundaries. Then if its big-endian, it might throw
the relevant bits of the int32_t entry into the high 4 bytes of the 8
byte word. I.e., the acCUR contents might just be overlapping the
*padding* that's put in front of the 32-bit entry. So what exactly do
I have to look again at?

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Aug 17 '06 #42

P: n/a
we******@gmail.com wrote:
Eric Sosman wrote:
>>we******@gmail.com wrote:
>>>Mikhail Teterin wrote:

So, comparing, say, 4-char arrays (like currency codes) can NOT be done in
the following way?

typedef union {
char acCUR[4];
int32_t iCUR;
} xCUR;
[...]

[...] Also the compiler is allowed to align struct entries as they
like. So on a 64 bit big endian system, the int32_t might not
intersect with any of the 4 acCur[] characters.

Agree with the first part but not with the second. Look
again: it's not a struct, but a union.

If the system is a 64 bit one, then it might force all entries to be
aligned to 64 bit boundaries. Then if its big-endian, it might throw
the relevant bits of the int32_t entry into the high 4 bytes of the 8
byte word. I.e., the acCUR contents might just be overlapping the
*padding* that's put in front of the 32-bit entry. So what exactly do
I have to look again at?
You could look at 6.5.8/5:

"[...] All pointers to members of the same union
object compare equal."

.... and at 6.7.2.1/14:

"[...] A pointer to a union object, suitably converted,
points to each of its members [...] and vice versa."

That is, there is no padding at the start of a union. The
four bytes (assuming CHAR_BIT==8) of the int32_t must occupy
the same four bytes as the char[4] array. If the union as a
whole is padded to eight bytes, the extra four are after the
int32_t and after the char[4], never before them.

Things would be different if he'd used int_least32_t or
int_fast32_t. With the exact-width int32_t he's on solid
ground (still assuming CHAR_BIT==8) as far as the overlap is
concerned, although he's on quicksand in other respects.

--
Eric Sosman
es*****@acm-dot-org.invalid
Aug 17 '06 #43

P: n/a
Mikhail Teterin wrote:
Keith Thompson wrote:
>Didn't we just go over this? Is there some reason you couldn't
have posted the C code as part of your article?

We did. And I ended up convinced, that only inertia (and the desire
to force a newcomer to obey the rules of the club), are what makes
this an issue in the first place.

People with news-readers, that are not MIME-aware will just see
these textual attachments as part of the article.

MIME-aware news-readers will be able to handle them better this way...

Sorry, if it were one file, I would've inlined it, but three --
that's just too much trouble.
I am restraining myself. Don't you realize there are good reasons
for these rules? Many systems will automatically strip any
attachments from news articles, or even destroy the article
altogether.

No, we don't automatically get together and harass all newbies for
the pure unadulterated pleasure of plaguing them. Yes, you are
suffering from paranoia.

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
Aug 17 '06 #44

P: n/a
we******@gmail.com wrote:
>I know. Currencies, however, are all 3-character strings (plus the
terminating '\0'). Thus they are perfectly suited to be treated as
int32_t, when convenient.

If that is true, then in fact this is a useful performance boost, but
its platform specific. Personally, I would just capture it like this:
*((int32_t *) &currency) rather than bothering with the union.
A plain string would not neccessarily allign the way an int32_t would
allign, would it? This can cause nasty SIGBUS-es...
>That it is not 100% portable is already rammed into me by the friendly
folks on this board. I'd like to know an example of the actual
hardware/compiler combo, where it would not work, though...

I am pretty sure there are real 64 bit systems (though likely they are
marginal) that will fail to do your trick correctly. Not AMD64, but
some old Crays or Sparc64s might in fact fail (they need to be big
Endian, and align struct/union entries to 64 bits).
That's why I used the union -- does not it ensure correctness even on these
8-byte alligning platforms? I thought, my only problem is with finding the
correct integer type to cover exactly the 4 characters.
And obviously those silly DSPs that don't support int32_t's would just
fail to compile your code.
Compile-time failure is acceptable -- it is the run-time, that worries me.

-mi

Aug 17 '06 #45

P: n/a
Eric Sosman wrote:
Elsethread you have posted an attempt to quantify HOW MUCH,
and your results suggest that the particular "cool" trick you
favor will save ...

0.00000000713037 seconds per comparison.
It is 4-6 times faster -- that, the relative, rather than absolute
difference -- is what counts.

A human being can not distinguish a millisecond from a microsecond.

Until the operation needs to be repeated a million time, that is. Because
millisecond becomes 16 minutes, while microsecond -- only a second.

An EOD (End-of-Day) process in a big bank/hedge fund makes (sometimes) many
millions of such currency comparisions as well as assignments (which don't
_really_ require a memcpy/strcpy), etc.

Using pessimal code for the sake of maintaining portability to Digital
Signal Processing boards is even more wasteful than owning an SUV for the
sake of an imaginary (but possible) once-in-a-lifetime off-road ride.
Mikhail, I can see your error and understand it and sympathize
Thank you, thank you. Agreeing to disagree.

-mi
Aug 17 '06 #46

P: n/a

Mikhail Teterin wrote:
Keith Thompson wrote:
Didn't we just go over this? Is there some reason you couldn't have
posted the C code as part of your article?

We did. And I ended up convinced, that only inertia (and the desire to force
a newcomer to obey the rules of the club), are what makes this an issue in
the first place.
What sort of response would have convinced you otherwise?

If the answer is, "There isn't one," then there doesn't
seem to be much point in talking to you, does there?

Aug 17 '06 #47

P: n/a
In article <16****************@aldan.algebra.com>,
Mikhail Teterin <us*********@aldan.algebra.comwrote:
>An EOD (End-of-Day) process in a big bank/hedge fund makes (sometimes) many
millions of such currency comparisions as well as assignments (which don't
_really_ require a memcpy/strcpy), etc.
>Using pessimal code for the sake of maintaining portability to Digital
Signal Processing boards is even more wasteful than owning an SUV for the
sake of an imaginary (but possible) once-in-a-lifetime off-road ride.
In that End-of-Day processing, is the bank/fund doing nothing when
the currencies do not match, or is the bank/fund doing a currency
conversion? If it is doing a conversion, then eliminate the check
by simply setting the conversion rate for all currencies to themselves
to be 1, and then unconditionally using the conversion routine
with the conversion factor indexed by both conversions.

But the point is moot, because we know that in the OP's code, the
OP is not primarily concerned with speed: the primary concern for
the OP is ease of debugging, and the code is intended by the OP to
be as fast as practical provided the ease of debugging is preserved.
If speed were the primary concern, then the OP's code would have
converted to an arbitrary currency index and then would compare the
indices "millions of times".
--
"law -- it's a commodity"
-- Andrew Ryan (The Globe and Mail, 2005/11/26)
Aug 17 '06 #48

P: n/a
Mikhail Teterin wrote:
Keith Thompson wrote:
I, for one, will ignore any attachments posted to this newsgroup.

I have not spent much time on this group, but, so far, I have not seen
anything that would make me truly saddened by your decision...
Then you are a fool.

Brian

Aug 17 '06 #49

P: n/a
We went from "don't do this, you idiot, the compiler is much better
optimizing, than you will ever be" to "yeah, it is 4-6 times faster to do
things your way, but it is still not worth the effort".

I think, this is a considerable progress for one thread and will shut up for
a while...

-mi
Aug 17 '06 #50

74 Replies

This discussion thread is closed

Replies have been disabled for this discussion.