473,386 Members | 1,827 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

replace bitfields with shifts and masks

I need to rewrite the following using shifts and masks for portability
sakes, and to get rid of the BYTE_ORDER issue.

/* CODE */
struct test {
#if BYTE_ORDER == BIG_ENDIAN
unsigned char ver:4;
unsigned char res1:4;
#else
unsigned char res1:4;
unsigned char ver:4;
#endif
unsigned char reserved2;
unsigned short checksum;
};

void
function(unsigned char *data)
{
struct test *t = (struct test *)data;

if (t.ver == 1) {
/* match */
}
}

/* END */

I was thinking I could just do the following, but it does not seem to work.

void
function(unsigned char *data)
{
uint32_t test = *(uint32_t *)data;

/* shift 28 bits, mask 4 */
if (((test >> 28) & 0x0f) == 1) {
/* match */
}
}

I am thinking the declaration is not correct.
Thanks for any help

- Dave
Jun 4 '06 #1
3 2408
In article <NP******************************@t-one.net>,
Dave <da***@wmol.com> wrote:
I need to rewrite the following using shifts and masks for portability
sakes, and to get rid of the BYTE_ORDER issue. /* CODE */
struct test {
#if BYTE_ORDER == BIG_ENDIAN
unsigned char ver:4;
unsigned char res1:4;
#else
unsigned char res1:4;
unsigned char ver:4;
#endif
unsigned char reserved2;
unsigned short checksum;
}; void
function(unsigned char *data)
{
struct test *t = (struct test *)data;

if (t.ver == 1) {
/* match */
}
}

/* END */ I was thinking I could just do the following, but it does not seem to work. void
function(unsigned char *data)
{
uint32_t test = *(uint32_t *)data; /* shift 28 bits, mask 4 */
if (((test >> 28) & 0x0f) == 1) {
/* match */
}
} I am thinking the declaration is not correct.


I'm not surprised it didn't work. You've made an improper
assumption that just because a byte occurs first in a structure,
that the byte will be the Most Significant Byte when the
structure is reinterpreted as an integer value. That assumption
mostly works out on strict big-endian machines, but it rarely
works out on little-endian machines.

What you need to know is that when a CPU loads several bytes
of memory to become a numeric value, that the byte order in
memory may well be not be the order the bytes will appear in the
numeric value. For example, if memory happens to have consequative
bytes 1 2 3 4, then when that block of bytes is loaded as an integer
value, the CPU register may hold 2 1 4 3 or 4 3 2 1 or any of
several other possible orders. Numeric value order is not certain
to be the same as the order written to memory. (This is not
a problem for the CPU because the scrambling/descrabling algorithm
is -consistant-.)

It is not sufficient to know that the machine is "big endian" or
"little endian", as there are 24 possible orders that can be used
to store 4 bytes. Two of those orders are in very common use,
but at least one other of them is common enough that it likely
will be encountered by a program that is intended to be portable.

There are easy run-time tests to determine what the byte
ordering is, and easy reordering routines.
--
There are some ideas so wrong that only a very intelligent person
could believe in them. -- George Orwell
Jun 4 '06 #2
Walter Roberson wrote:
In article <NP******************************@t-one.net>,
Dave <da***@wmol.com> wrote:
I need to rewrite the following using shifts and masks for portability
sakes, and to get rid of the BYTE_ORDER issue.

/* CODE */
struct test {
#if BYTE_ORDER == BIG_ENDIAN
unsigned char ver:4;
unsigned char res1:4;
#else
unsigned char res1:4;
unsigned char ver:4;
#endif
unsigned char reserved2;
unsigned short checksum;
};

void
function(unsigned char *data)
{
struct test *t = (struct test *)data;

if (t.ver == 1) {
/* match */
}
}

/* END */

I was thinking I could just do the following, but it does not seem to work.

void
function(unsigned char *data)
{
uint32_t test = *(uint32_t *)data;

/* shift 28 bits, mask 4 */
if (((test >> 28) & 0x0f) == 1) {
/* match */
}
}

I am thinking the declaration is not correct.


I'm not surprised it didn't work. You've made an improper
assumption that just because a byte occurs first in a structure,
that the byte will be the Most Significant Byte when the
structure is reinterpreted as an integer value. That assumption
mostly works out on strict big-endian machines, but it rarely
works out on little-endian machines.

What you need to know is that when a CPU loads several bytes
of memory to become a numeric value, that the byte order in
memory may well be not be the order the bytes will appear in the
numeric value. For example, if memory happens to have consequative
bytes 1 2 3 4, then when that block of bytes is loaded as an integer
value, the CPU register may hold 2 1 4 3 or 4 3 2 1 or any of
several other possible orders. Numeric value order is not certain
to be the same as the order written to memory. (This is not
a problem for the CPU because the scrambling/descrabling algorithm
is -consistant-.)

It is not sufficient to know that the machine is "big endian" or
"little endian", as there are 24 possible orders that can be used
to store 4 bytes. Two of those orders are in very common use,
but at least one other of them is common enough that it likely
will be encountered by a program that is intended to be portable.

There are easy run-time tests to determine what the byte
ordering is, and easy reordering routines.


Doh, I forgot ntohl() :P

Thanks
Jun 4 '06 #3
>In article <NP******************************@t-one.net>,
Dave <da***@wmol.com> wrote:
I need to rewrite the following using shifts and masks for portability
sakes, and to get rid of the BYTE_ORDER issue.
/* CODE */
struct test {
#if BYTE_ORDER == BIG_ENDIAN
unsigned char ver:4;
unsigned char res1:4;
#else
unsigned char res1:4;
unsigned char ver:4;
#endif
unsigned char reserved2;
unsigned short checksum;
};
This is apparently an attempt to "fake up" a representation clause
for something that, in C, is best described as:

unsigned char buf[4];

(but note that the "checksum" is now in individual "C byte" pieces
rather than one probably-larger unit; now *you* control the order
of the pieces, instead of letting the compiler do it, much as you
now control the order of the bitfields within the first "C byte").

If your target machine has greater-than-8-bit "C bytes" ("char"s),
you may still have some problems, but they are problems you were
going to have no matter what.
void
function(unsigned char *data)
{
uint32_t test = *(uint32_t *)data;

/* shift 28 bits, mask 4 */
if (((test >> 28) & 0x0f) == 1) {
/* match */
}
}

I am thinking the declaration is not correct.


In article <e5**********@canopus.cc.umanitoba.ca>
Walter Roberson <ro******@ibd.nrc-cnrc.gc.ca> wrote:It is not sufficient to know that the machine is "big endian" or
"little endian", as there are 24 possible orders that can be used
to store 4 bytes. Two of those orders are in very common use,
but at least one other of them is common enough that it likely
will be encountered by a program that is intended to be portable.


Or, more simply, treat the array of bytes as an array of bytes.
Stop giving up control of the layout. Extract byte #0 and shift
and mask as needed:

if (((data[0] >> 4) & 0x0f) == 1) {
...
}

(If you deal with the individual bytes of data as individual bytes
of data, you never need tricks like "htonl" either.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jun 4 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Jon Slaughter | last post by:
I'm using bit fields to compactly represent some data I need to manage and I've read that they are not portable. I don't understand why that is the case? As long as I don't "indirectly" mess with...
8
by: Régis Troadec | last post by:
Hi all, I follow c.l.c. for only a short time and I would like to know why there isn't anything concerning bitfields among the FAQs. Is it because ... 1. of portability issues? 2. bitfields...
23
by: rohit | last post by:
Hi, In my couple of years of experience, I have never found a single instance where I needed to use unions and bitfields(though I have used structures).I was just imagining where would these find...
6
by: GalenTX | last post by:
I am looking for opinions on a possible approach to coping with bitfields in a heterogenous environment. We've got a bunch of legacy code which maps to hardware using bitfields. The code was...
19
by: Mehta Shailendrakumar | last post by:
Hi, I would like to know why array of bitfields is not possible. Is there any relation with processor architecture for this? Thank you for your time. Regards, Shailendra
18
by: richard_l | last post by:
Hello All, I am writing an application which receives a word which is a bitmap. I have created a word typedef which contains a bitfield defining each bit. however, I was wondering however if it...
3
by: Unbridled | last post by:
I am looking for the syntax to add information to information that is already in a field. I am trying to add or replace a value to a field (org_perm_id) for those that have not posted in 30 days on...
9
by: cman | last post by:
Who can explain to me what bitfields are and how to use them in practice? I would need a fairly detailed explaination, I would be a newbie to advanced C programming features. What are the...
10
by: lithiumcat | last post by:
Hi, This question seems to come up quite often, however I haven't managed to find an answer relevant to my case. I often use binary flags, and I have alaways used a "bitmask" technique, that...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.