/* 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
*/ 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 .
"- 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
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.
- 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.
}
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 **
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;
"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
- 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.
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.
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
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
- 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!
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! This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: ajay |
last post by:
Why would a new of object be created without assigning it to any of variable?
new A;
???
tx
|
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...
|
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...
|
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 ;-) )
|
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...
|
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);...
|
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?
|
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";
|
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...
|
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...
|
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...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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....
|
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...
| |