473,322 Members | 1,522 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,322 software developers and data experts.

assigning bit-field structure

/* With the following: */
typedef struct
{
unsigned char a : 1;
unsigned char b : 1;
} sss_t;
sss_t sss;
unsigned char ppp;

main()
{
sss = (sss_t)ppp; /* why 'invalid cast expression'? */

sss = *(sss_t*)&ppp; /* why OK? */
}

/*
Used Sun compiler.

Thanks,

Kees
*/

Nov 14 '05 #1
13 11458


- Kees van der Bent - wrote:
/* With the following: */
typedef struct
{
unsigned char a : 1;
unsigned char b : 1;
} sss_t;
sss_t sss;
unsigned char ppp;

main()
{
sss = (sss_t)ppp; /* why 'invalid cast expression'? */
You are trying to convert an unsigned char to an user-defined data
type, that are noway related , as far as the compiler is concerned.

sss = *(sss_t*)&ppp; /* why OK? */


&ppp changes it to UCHAR * , and then you are converting to (sss_t
*) [ it really gets dangerous here, but you are allowed to do it, since
they are addresses after all ] .
Having converted it, you are dereferencing it back. I am assuming you
are writing this for learning purposes only. But as such , such cast
expressions ( changing pointers of a given type to a diff. type ) ought
not to be used in any serious project ;) .

HTH .
Nov 14 '05 #2
"- Kees van der Bent -" <kv*@mbalance.moc> wrote in message
news:40*********************@news.xs4all.nl...
/* With the following: */
typedef struct
{
unsigned char a : 1;
unsigned char b : 1;
} sss_t;
sss_t sss;
unsigned char ppp;
Why are these global?
main()
{
sss = (sss_t)ppp; /* why 'invalid cast expression'? */
You're not gonna like it, but you can't do it, because... you can't do it!
You cannot cast between a scalar and an aggregate type. Think of it this
way: an aggregate (such as a structure) is an object containing more than
one value (even if the structure contains only one field, we are talking in
general terms here). A scalar only contains one value. How would you convert
from one to another? What sense would it make?
sss = *(sss_t*)&ppp; /* why OK? */
Conversions between pointers are allowed. Whether the result of such
conversion is meaningful, or even a valid pointer, is quite another
question.
}

/*
Used Sun compiler.
Doesn't matter.
Thanks,

Kees
*/


Peter
Nov 14 '05 #3
Rakesh <dr******************@yahoo.com> spoke thus:
&ppp changes it to UCHAR * , and then you are converting to (sss_t

^^^^^
ITYM "unsigned char". UCHAR is not a C keyword, although of course
you can typedef it yourself if you're so inclined.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #4
- Kees van der Bent - wrote:
/* With the following: */
typedef struct
{
unsigned char a : 1;
unsigned char b : 1;
unsigned char is not a valid type for a bit field.
} sss_t;
sss_t sss;
unsigned char ppp;

main()
{
sss = (sss_t)ppp; /* why 'invalid cast expression'? */
ppp is a scalar; the type sss_t isn't.
sss = *(sss_t*)&ppp; /* why OK? */
Because C lets you do all sorts of silly things using pointers.
}

Nov 14 '05 #5
Oh yeah :) of course , i meant unsigned char . I was a bit too lazy to
type in that. Thanks for pointing it out, though.

Christopher Benson-Manica wrote:
Rakesh <dr******************@yahoo.com> spoke thus:

&ppp changes it to UCHAR * , and then you are converting to (sss_t


^^^^^
ITYM "unsigned char". UCHAR is not a C keyword, although of course
you can typedef it yourself if you're so inclined.


--

--
Rakesh Kumar
** Remove nospamplz from my email address for my real email **
Nov 14 '05 #6
Martin Ambuhl <ma*****@earthlink.net> wrote in message news:<c6************@ID-227552.news.uni-berlin.de>...
- Kees van der Bent - wrote:
/* With the following: */
typedef struct
{
unsigned char a : 1;
unsigned char b : 1;
unsigned char is not a valid type for a bit field.


Yes I read this in K&R and wondered why the compiler did not
warn at all. What do you think?
} sss_t;

Nov 14 '05 #7
"Peter Pichler" <pi*****@pobox.sk> wrote in message news:<40********@mk-nntp-2.news.uk.tiscali.com>...
"- Kees van der Bent -" <kv*@mbalance.moc> wrote in message
news:40*********************@news.xs4all.nl...
/* With the following: */
typedef struct
{
unsigned char a : 1;
unsigned char b : 1;
} sss_t;
sss_t sss;
unsigned char ppp;
Why are these global?


I quickly typed in a small piece of code that gave the
same results as my real code. I don't like globals either.
main()
{
sss = (sss_t)ppp; /* why 'invalid cast expression'? */
You're not gonna like it, but you can't do it, because... you can't do it!
You cannot cast between a scalar and an aggregate type. Think of it this
way: an aggregate (such as a structure) is an object containing more than
one value (even if the structure contains only one field, we are talking in
general terms here). A scalar only contains one value. How would you convert
from one to another? What sense would it make?


I like to view a bit-field structure as a special case of of scalar:
a regular scalar with the added convenience of being able to 'address'
certain bits. Isn't this how bit-fields are used in hardware device
drivers (mapping certain registers)?

In my case my input data is of type unsigned char which needs to be
mapped/assigned on/to a bit-field structure. Instead of writing out
all the nuts al bolts (with ... >> 4 & 0x3 ...) I want C to help me
out here and let the compiler do the work for me.
sss = *(sss_t*)&ppp; /* why OK? */
Conversions between pointers are allowed. Whether the result of such
conversion is meaningful, or even a valid pointer, is quite another
question.


I agree with you. But this seems to be the only way to get the result
I want. Although I'm confident that this will work in practice, the
question remains if this works according to the C standard. How is bit-
field structure allignment specified in the C spec?
}

/*
Used Sun compiler.


Doesn't matter.
Thanks,

Kees
*/


Peter

Nov 14 '05 #8
- Kees van der Bent - wrote:
Martin Ambuhl <ma*****@earthlink.net> wrote in message news:<c6************@ID-227552.news.uni-berlin.de>...
- Kees van der Bent - wrote:
/* With the following: */
typedef struct
{
unsigned char a : 1;
unsigned char b : 1;


unsigned char is not a valid type for a bit field.

Yes I read this in K&R and wondered why the compiler did not
warn at all. What do you think?


That you either don't have the diagnostic level set properly or that you
are not invoking your compiler in conforming mode.
Nov 14 '05 #9
In article <news:f5************************@posting.google.co m>
- Kees van der Bent - <kv*****@mail.com> writes:
I like to view a bit-field structure as a special case of of scalar:
a regular scalar with the added convenience of being able to 'address'
certain bits. Isn't this how bit-fields are used in hardware device
drivers (mapping certain registers)?
Some people write code like that. Others write code that survives
changing compilers. :-)
In my case my input data is of type unsigned char which needs to be
mapped/assigned on/to a bit-field structure. Instead of writing out
all the nuts al bolts (with ... >> 4 & 0x3 ...) I want C to help me
out here and let the compiler do the work for me.
Unfortunately, as Dennis Ritchie himself once put it, C's bitfields
are "a botch and a blemish". For instance:
How is bit-field structure allignment specified in the C spec?


It is not.

Much worse, however, is the fact that two different compilers FOR THE
SAME MACHINE may reverse the order of the bits in some bitfield:

/* device connected to motorola 68010; C compiler has 16-bit int */
struct hardware_reg {
unsigned int go:1; /* set to 1 to make device run */
unsigned int cmd:3; /* command */
unsigned int ctl:4; /* control bits */
unsigned int dma:1; /* set to 1 to use DMA */
unsigned int :3; /* unused */
unsigned int status:4; /* device status */
unsigned int addr; /* DMA address */
};

Compiled with Compiler A, the "go" bit is (as desired) the high bit
of the first 16-bit word, but compiled with Compiler B, the "go" bit
becomes the *low* bit of that word.

Using "unsigned short csr, addr;" and defining bits for the control
and status register works on every compiler you will find for that
68010-based system (even those with 32-bit ints). C gives you (the
programmer) no control whatsoever of where the bits in the bitfield
wind up. If you want to write this sort of code, you might consider
Ada, which has the necessary construct (the "representation clause").
--
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.
Nov 14 '05 #10
In <c6*********@news3.newsguy.com> Chris Torek <no****@torek.net> writes:
In article <news:f5************************@posting.google.co m>
- Kees van der Bent - <kv*****@mail.com> writes:
How is bit-field structure allignment specified in the C spec?


It is not.

Much worse, however, is the fact that two different compilers FOR THE
SAME MACHINE may reverse the order of the bits in some bitfield:

/* device connected to motorola 68010; C compiler has 16-bit int */
struct hardware_reg {
unsigned int go:1; /* set to 1 to make device run */
unsigned int cmd:3; /* command */
unsigned int ctl:4; /* control bits */
unsigned int dma:1; /* set to 1 to use DMA */
unsigned int :3; /* unused */
unsigned int status:4; /* device status */
unsigned int addr; /* DMA address */
};

Compiled with Compiler A, the "go" bit is (as desired) the high bit
of the first 16-bit word, but compiled with Compiler B, the "go" bit
becomes the *low* bit of that word.

Using "unsigned short csr, addr;" and defining bits for the control
and status register works on every compiler you will find for that
68010-based system (even those with 32-bit ints). C gives you (the
programmer) no control whatsoever of where the bits in the bitfield
wind up.


It's a tradeoff between portability and readability. You can provide
two different definitions for struct hardware_reg and select between
them according to the compiler being used. Such code is using plenty of
extensions anyway, so it's not portable code.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #11
Dan Pop wrote:
In <c6*********@news3.newsguy.com> Chris Torek <no****@torek.net> writes:

In article <news:f5************************@posting.google.co m>
- Kees van der Bent - <kv*****@mail.com> writes:

How is bit-field structure allignment specified in the C spec?


It is not.

Much worse, however, is the fact that two different compilers FOR THE
SAME MACHINE may reverse the order of the bits in some bitfield:

/* device connected to motorola 68010; C compiler has 16-bit int */
struct hardware_reg {
unsigned int go:1; /* set to 1 to make device run */
unsigned int cmd:3; /* command */
unsigned int ctl:4; /* control bits */
unsigned int dma:1; /* set to 1 to use DMA */
unsigned int :3; /* unused */
unsigned int status:4; /* device status */
unsigned int addr; /* DMA address */
};

Compiled with Compiler A, the "go" bit is (as desired) the high bit
of the first 16-bit word, but compiled with Compiler B, the "go" bit
becomes the *low* bit of that word.

Using "unsigned short csr, addr;" and defining bits for the control
and status register works on every compiler you will find for that
68010-based system (even those with 32-bit ints). C gives you (the
programmer) no control whatsoever of where the bits in the bitfield
wind up.

It's a tradeoff between portability and readability. You can provide
two different definitions for struct hardware_reg and select between
them according to the compiler being used. Such code is using plenty of
extensions anyway, so it's not portable code.

Dan


This sub-thread made me decide to make my code portable using >> & ...
Thanks for the help and sharing info about C and its implementations.

Kees

Nov 14 '05 #12
- Kees van der Bent - wrote:
/* With the following: */
typedef struct
{
unsigned char a : 1;
unsigned char b : 1;
} sss_t;
sss_t sss;
unsigned char ppp;

main()
{
sss = (sss_t)ppp; /* why 'invalid cast expression'? */

sss = *(sss_t*)&ppp; /* why OK? */
}

/*
Used Sun compiler.

Thanks,

Kees
*/


There is an elegant way to solve your problem: use unions.
Here the c member represents the 'whole' unsigned char while a and b are
bits of that unsigned char.

#include <stdio.h>

typedef union
{
struct
{
unsigned char a : 1;
unsigned char b : 1;
} u;
unsigned char c;
} sss_t;

main()
{
sss_t sss;
sss.c = 1;
printf("sizeof(sss) = %d\n", sizeof(sss));
printf("sss.c = %d, sss.a = %d, sss.b = %d\n", sss.c, sss.u.a,
sss.u.b);
sss.c = 2;
printf("sss.c = %d, sss.a = %d, sss.b = %d\n", sss.c, sss.u.a,
sss.u.b);
return 0;
}

The output of the program is:

sizeof(sss) = 1
sss.c = 1, sss.a = 1, sss.b = 0
sss.c = 2, sss.a = 0, sss.b = 1

I used gcc-3.3.3. Please note that not all compilers will generate a
structure with size!
Nov 14 '05 #13
Still the C spec does not specify the bit order of the fields. This
construct can therefore not be used for mapping hardware registers.
Thanks for the idea anyway; although I chose another implementation,
I did not think of using a union at all.

Cheers,

Kees

Henri Manson wrote:
There is an elegant way to solve your problem: use unions.
Here the c member represents the 'whole' unsigned char while a and b are
bits of that unsigned char.

#include <stdio.h>

typedef union
{
struct
{
unsigned char a : 1;
unsigned char b : 1;
} u;
unsigned char c;
} sss_t;

main()
{
sss_t sss;
sss.c = 1;
printf("sizeof(sss) = %d\n", sizeof(sss));
printf("sss.c = %d, sss.a = %d, sss.b = %d\n", sss.c, sss.u.a,
sss.u.b);
sss.c = 2;
printf("sss.c = %d, sss.a = %d, sss.b = %d\n", sss.c, sss.u.a,
sss.u.b);
return 0;
}

The output of the program is:

sizeof(sss) = 1
sss.c = 1, sss.a = 1, sss.b = 0
sss.c = 2, sss.a = 0, sss.b = 1

I used gcc-3.3.3. Please note that not all compilers will generate a
structure with size!


Nov 14 '05 #14

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

Similar topics

22
by: ajay | last post by:
Why would a new of object be created without assigning it to any of variable? new A; ??? tx
4
by: jonas.email | last post by:
Im am doing a major project and after a long time debugging i found this rather funny (=annoying) bug. In its simple form, this is the main problem: int main(void) { float f1 = 0.3f; float f2...
6
by: adamrfrench | last post by:
Let it be mentioned that Javascript is not my forte, so the solution to this could very well be a simple one. I am working on an AJAX function where I can pass a URL and the target ID in, and...
12
by: bollod | last post by:
Is there any benefit to declaring a variable: x = (1<<12); instead of: x = 4096; (besides the geek appeal of course ;-) )
10
by: Linny | last post by:
Hi All, I am pasting a piece of code which executes fine on 32 bit system but fails with a segmentation fault when compiled 64 bit compiler.I am using a HP-UX C compiler on PA-RISC system. This...
27
by: csledge | last post by:
Hi, I am trying to compute a 64 bit result from 2 32 bit registers, How do I get the carry into the higher word ? Also is %lld correct ? #include<stdio.h> long long int64( long x, int y);...
4
by: Felix Kater | last post by:
Hi, when I use something like int Shift= 3; long Value= 1 << Shift; What is the data type of the const value '1' here? In other terms: What is the possible maximum of 'Shift' here?
43
by: emyl | last post by:
Hi all, here's an elementary question. Assume I have declared two variables, char *a, **b; I can then give a value to a like a="hello world";
1
by: The Pythonista | last post by:
I've been wondering for a while about whether assigning to __class__ is bad form or not. Specifically, I mean doing so when some other method of implementing the functionality you're after is...
9
by: shortyzms | last post by:
I'm having a problem with assigning 64-bit hex values to unsigned long variables in MS VS2005 c++ compiler. unsigned long Number; Number = 0x1000000000000000UL; After this declaration and...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

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.