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

wtf is this?

This is the first time I have seen code like this and I don't know what
it means. It appears to be C code but I thought I was familiar with
most constructs...must have missed one:

u_char c_perm : 3;

This declairation is inside of a struct along with several other
variables declaired in a similar manner.

I am assuming u_char to be a typedef for unsigned char, but what is the
" : 3" part doing there and what does it mean? Is this new syntax from
C99 or has it always been around and I just never ran into it before?

I found this code in the Xok exokernel from MIT if it makes a diff or
you are curious.

Thanks,
NR

Nov 13 '05 #1
10 1640
Noah Roberts wrote:
This is the first time I have seen code like this and I don't know what
it means. It appears to be C code but I thought I was familiar with
most constructs...must have missed one:

u_char c_perm : 3;


You hold off asking until you are sure you can't find the answer and
then you do :P I actually knew what this was I just hadn't ever seen it
used so forgot all about it. I have never actually seen code that used
bitfields, and that isn't the only strange thing it does:
/* An array of seven (7--I'm cheating) bytes naming the capability if
* it is not a pointer: */
u_char c_name[1];
/* The length and address of the capability list if this is a pointer: */
u_short cl_len;
struct Capability *cl_list;

Of course this code is not meant to be exactly portable :P

NR

Nov 13 '05 #2
"Noah Roberts" <nr******@dontemailme.com> wrote in message
news:bl**********@quark.scn.rain.com...
Noah Roberts wrote:
This is the first time I have seen code like this and I don't know what
it means. It appears to be C code but I thought I was familiar with
most constructs...must have missed one:

u_char c_perm : 3;
You hold off asking until you are sure you can't find the answer and
then you do :P I actually knew what this was I just hadn't ever seen it >

used so forgot all about it. I have never actually seen code that used bitfields, and that isn't the only strange thing it does:
What do you find strange?


/* An array of seven (7--I'm cheating) bytes naming the capability if
* it is not a pointer: */
u_char c_name[1];
That's an array of *one* type 'u_char' object.
/* The length and address of the capability list if this is a pointer: */
u_short cl_len;
struct Capability *cl_list;

Of course this code is not meant to be exactly portable :P


If 'u_char' and 'u_short' are typedefs for standard
types, then yes, it's portable.

-Mike
Nov 13 '05 #3

"Noah Roberts" <nr******@dontemailme.com> wrote in message
news:bl**********@quark.scn.rain.com...
This is the first time I have seen code like this and I don't know what
it means. It appears to be C code but I thought I was familiar with
most constructs...must have missed one:

u_char c_perm : 3;

This declairation is inside of a struct along with several other
variables declaired in a similar manner.

I am assuming u_char to be a typedef for unsigned char, but what is the
" : 3" part doing there and what does it mean? Is this new syntax from
C99 or has it always been around and I just never ran into it before?


It's been around quite a while. Look up 'bitfield'.

-Mike
Nov 13 '05 #4
Mike Wahler wrote:
/* An array of seven (7--I'm cheating) bytes naming the capability if
* it is not a pointer: */
u_char c_name[1];

That's an array of *one* type 'u_char' object.


By the comments I would gather that it is being used as *7*. Glad you
noticed the 1 there though. Kind of interesting that someone would
create an array of 1 element...
/* The length and address of the capability list if this is a pointer: */
u_short cl_len;
struct Capability *cl_list;

Of course this code is not meant to be exactly portable :P

If 'u_char' and 'u_short' are typedefs for standard
types, then yes, it's portable.

Ahhhh...that's right; short == 2 bytes and pointer == 4, always...I knew
I was missing something there...guess I should have looked at it more.

Cute optimization, but I know *I* wouldn't call it portable...but like I
said, in this domain it doesn't need or even want to be.

NR

Nov 13 '05 #5
In <HA*****************@newsread4.news.pas.earthlink. net> "Mike Wahler" <mk******@mkwahler.net> writes:
"Noah Roberts" <nr******@dontemailme.com> wrote in message
news:bl**********@quark.scn.rain.com...
Noah Roberts wrote:
> This is the first time I have seen code like this and I don't know what
> it means. It appears to be C code but I thought I was familiar with
> most constructs...must have missed one:
>
> u_char c_perm : 3;


You hold off asking until you are sure you can't find the answer and
then you do :P I actually knew what this was I just hadn't ever seen it >

used so forgot all about it. I have never actually seen code that used
bitfields, and that isn't the only strange thing it does:


What do you find strange?


The fact that the bit field has the type u_char, which is seldom used as
an alias for unsigned int.

A bit-field may have type int, unsigned int, or signed int.
Whether the high-order bit position of a ``plain'' int bit-field is
treated as a sign bit is implementation-defined. A bit-field is
interpreted as an integral type consisting of the specified number of
bits.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #6

"Noah Roberts" <nr******@dontemailme.com> wrote in message
news:bl**********@quark.scn.rain.com...
Mike Wahler wrote:
/* An array of seven (7--I'm cheating) bytes naming the capability if
* it is not a pointer: */
u_char c_name[1];

That's an array of *one* type 'u_char' object.


By the comments I would gather that it is being used as *7*. Glad you
noticed the 1 there though. Kind of interesting that someone would
create an array of 1 element...

/* The length and address of the capability list if this is a pointer: */ u_short cl_len;
struct Capability *cl_list;

Of course this code is not meant to be exactly portable :P

If 'u_char' and 'u_short' are typedefs for standard
types, then yes, it's portable.

Ahhhh...that's right; short == 2 bytes and pointer == 4, always

Not true.
...I knew
I was missing something there...guess I should have looked at it more.

Cute optimization,
I see no 'optimization', only obfuscation.
but I know *I* wouldn't call it portable...
Why not?
but like I
said, in this domain it doesn't need or even want to be.


No, much software is necessarily nonportable. This is
not a 'bad thing', but being unaware of it is.
-Mike
Nov 13 '05 #7

On Mon, 29 Sep 2003, Mike Wahler wrote:

"Noah Roberts" <nr******@dontemailme.com> wrote:
Mike Wahler wrote:
[Noah wrote:]
>/* An array of seven (7--I'm cheating) bytes naming the capability if
> * it is not a pointer: */
> u_char c_name[1];

That's an array of *one* type 'u_char' object.


By the comments I would gather that it is being used as *7*. Glad you
noticed the 1 there though. Kind of interesting that someone would
create an array of 1 element...
>/* The length and address of the capability list if this is a pointer: */> u_short cl_len;
> struct Capability *cl_list;
>
>Of course this code is not meant to be exactly portable :P

If 'u_char' and 'u_short' are typedefs for standard
types, then yes, it's portable.
Ahhhh...that's right; short == 2 bytes and pointer == 4, always


Not true.

I can't tell whether Noah's response there was supposed to be
tongue-in-cheek or not. But the code is a perfectly valid
optimization [and obfuscation] for your average x86 platform
(although, as Noah points out, non-portable). The portable
equivalent would have been

union {
char c_name[7];
struct {
char c_name[1];
unsigned short cl_len;
struct Capability *cl_list;
} rest;
} my_data;
So where old code might have written

if (c_name[0] == '\0')
process(&cl_len, &cl_list);
else
okay = strcmp(c_name, "SIXCHR");

the new, portable version would read

if (my_data.c_name[0] == '\0')
process(&my_data.rest.cl_len, &my_data.rest.cl_list);
else
okay = strcmp(my_data.c_name, "SIXCHR");

In the case that no structure padding is used, and sizeof(short)==2
and sizeof(struct Capability *)==4, then we have a data layout that
basically replicates the x86-compiler-specific code.

...I knew
I was missing something there...guess I should have looked at it more.

Cute optimization,


I see no 'optimization', only obfuscation.


Ditto. The six-byte savings is not worth the unportability.
but I know *I* wouldn't call it portable...


Why not?


'Cause it isn't. :-) Although a c.l.c regular might be
forgiven for his relative abundance of tree-vision over
forest-vision in this case... ;-)

HTH,
-Arthur

Nov 13 '05 #8
Arthur J. O'Dwyer wrote:
Ahhhh...that's right; short == 2 bytes and pointer == 4, always
Not true.


I can't tell whether Noah's response there was supposed to be
tongue-in-cheek or not.


Yeah, I was being a smartass.

But the code is a perfectly valid optimization [and obfuscation] for your average x86 platform
(although, as Noah points out, non-portable).
And since this is a kernel only ever meant to be run on an x86 this is
ok. Certainly obfuscated, but not that badly; I would prefer the union
version myself as it confused me at first. I would bet it would work on
most current systems at any rate, you would only need to worry if one of
the last two where too small to hold 6 bytes.

The portable equivalent would have been

union {
char c_name[7];
struct {
char c_name[1];
unsigned short cl_len;
struct Capability *cl_list;
} rest;
} my_data;
So where old code might have written

if (c_name[0] == '\0')
process(&cl_len, &cl_list);
else
okay = strcmp(c_name, "SIXCHR");

the new, portable version would read

if (my_data.c_name[0] == '\0')
process(&my_data.rest.cl_len, &my_data.rest.cl_list);
else
okay = strcmp(my_data.c_name, "SIXCHR");

In the case that no structure padding is used, and sizeof(short)==2
and sizeof(struct Capability *)==4, then we have a data layout that
basically replicates the x86-compiler-specific code.
Can we be sure that there is no padding in the x86 specific version?
I see no 'optimization', only obfuscation.

Ditto. The six-byte savings is not worth the unportability.


The portability issue is not a major issue in this case. This code is
meant to expose the underlying hardware through a secure interface; you
can't really do that portably. Also, this is a much used component
inside of a kernel. These objects will be passed with any system call
an application makes or tied to an internal representation of the
process (haven't gotten that far yet). It might be worth it in this
special case.

but I know *I* wouldn't call it portable...


Why not?

'Cause it isn't. :-) Although a c.l.c regular might be
forgiven for his relative abundance of tree-vision over
forest-vision in this case... ;-)


That's why I said I should have looked harder :P Mike is usually pretty
on the point, I think he just read this one too fast or something.

NR

Nov 13 '05 #9

On Mon, 29 Sep 2003, Noah Roberts wrote:

Arthur J. O'Dwyer wrote:
Ahhhh...that's right; short == 2 bytes and pointer == 4, always

Not true.
I can't tell whether Noah's response there was supposed to be
tongue-in-cheek or not.


Yeah, I was being a smartass.


Okay. You're gonna have to try harder next time; looks like
[almost] everyone missed it. ;-)
But the code is a perfectly valid
optimization [and obfuscation] for your average x86 platform
(although, as Noah points out, non-portable).


And since this is a kernel only ever meant to be run on an x86 this is
ok. Certainly obfuscated, but not that badly; I would prefer the union
version myself as it confused me at first.


I *strongly* recommend the union version over the current version.
Because at the moment, the code is just *begging* for some clever
maintainer to re-arrange the global variables so that the pointer
comes first, then the short, then the char[1] (in the interests of
removing some padding bytes, on compilers that do that). Once
someone does that, the code will become entirely broken and will
cause incredibly hard-to-find system bugs. In a kernel, that's
bad. :-(
I would bet it would work on
most current systems at any rate, you would only need to worry if one of
the last two where too small to hold 6 bytes.
Which is entirely possible. *Especially* on an x86, where
2-byte pointers are the easiest thing to use, in programs not
exceeding one segment's-worth of data. Again, crashes and
Bad Things. [Hmm... this optimization is looking less and less
"perfectly valid" the more I think about it...]
The portable
equivalent would have been

union {
char c_name[7];
struct {
char c_name[1];
unsigned short cl_len;
struct Capability *cl_list;
} rest;
} my_data;
In the case that no structure padding is used, and sizeof(short)==2
and sizeof(struct Capability *)==4, then we have a data layout that
basically replicates the x86-compiler-specific code.


Can we be sure that there is no padding in the x86 specific version?


No. But the code was obviously written with the *assumption* that
there wouldn't be any. (Oh, and BTW, it's not *really* x86-specific.
It's specific to any compiler+architecture with the right size
data, the right alignment requirements, and the right strategy for
allocating variables in memory.)

I see no 'optimization', only obfuscation.


Ditto. The six-byte savings is not worth the unportability.


The portability issue is not a major issue in this case. This code is
meant to expose the underlying hardware through a secure interface; you
can't really do that portably.


But you *can* do *this* little bit of it portably. So why not
take the five minutes and make it portable? ...And if the modification
takes more than five minutes, then you're in more trouble than I
thought! :-)
Also, this is a much used component
inside of a kernel. These objects will be passed with any system call
an application makes or tied to an internal representation of the
process (haven't gotten that far yet). It might be worth it in this
special case.


It's all just bits and bytes at the machine level. The compiler
really won't care whether you wrap things in a struct or not, trust
me.
*Some* optimizations do help dumb compilers in a real sense --
for example, loop unrolling or use of the 'register' keyword can
really help some compilers limp along. But in this case, I don't
see any way that wrapping up the variables safely could possibly
hurt your performance. They keep the same addresses and everything.

If you're really curious about performance questions, you
should compile both versions and examine the assembly output.
If you *still* want help, consult someone or some group where
your particular compiler or architecture is on-topic. I.e.,
not comp.lang.c, anymore, because this discussion IMHO has
drifted too far off-topic.

HTH,
-Arthur
Nov 13 '05 #10
Arthur J. O'Dwyer wrote:
Which is entirely possible. *Especially* on an x86, where
2-byte pointers are the easiest thing to use, in programs not
exceeding one segment's-worth of data. Again, crashes and
Bad Things. [Hmm... this optimization is looking less and less
"perfectly valid" the more I think about it...]
Hey, it is from MIT, it must be right.
I see no 'optimization', only obfuscation.

Ditto. The six-byte savings is not worth the unportability.

[snip] It's all just bits and bytes at the machine level. The compiler
really won't care whether you wrap things in a struct or not, trust
me.


Yeah, there really shouldn't be such a thing as struct and union once it
is compiled, except possibly longer symbols (at a kernel level would
these exist or would it only use addresses?). I assumed you had meant a
six byte saving over this:

u_char name[7];
u_short whatever;
struct Capability* list;

I totally agree, it isn't pretty and the union version is better.

NR

Nov 13 '05 #11

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

Similar topics

4
by: James | last post by:
I have a from with 2 fields: Company & Name Depening which is completed, one of the following queries will be run: if($Company){ $query = "Select C* From tblsample Where ID = $Company...
5
by: Scott D | last post by:
I am trying to check and see if a field is posted or not, if not posted then assign $location which is a session variable to $location_other. If it is posted then just assign it to...
2
by: Nick | last post by:
Can someone please tell me how to access elements from a multiple selection list? From what ive read on other posts, this is correct. I keep getting an "Undefined variable" error though... Form...
2
by: Alexander Ross | last post by:
I have a variable ($x) that can have 50 different (string) values. I want to check for 7 of those values and do something based on it ... as I see it I have 2 options: 1) if (($x=="one") ||...
0
by: Dan Foley | last post by:
This script runs fine, but I'd like to know why it's so slow.. Thanks for any help out there on how i can make it faster (it might take up to 5 min to write these 3 export files whith 15 records...
5
by: Lee Redeem | last post by:
Hi there I've created abd uploaded this basic PHP script: <html> <head> <title>PHP Test</title> </head> <body> <H1 align="center">
5
by: christopher vogt | last post by:
Hi, i'm wondering if there is something like $this-> to call a method inside another method of the same class without using the classname in front. I actually use class TEST { function...
6
by: Phil Powell | last post by:
Ok guys, here we go again! SELECT s.nnet_produkt_storrelse_navn FROM nnet_produkt_storrelse s, nnet_produkt_varegruppe v, nnet_storrelse_varegruppe_assoc sv, nnet_produkt p WHERE...
1
by: Michel | last post by:
a site like this http://www.dvdzone2.com/dvd Can you make it in PHP and MySQL within 6 weeks? If so, send me your price 2 a r a (at) p a n d o r a . b e
11
by: Maciej Nadolski | last post by:
Hi! I can`t understand what php wants from me:( So: Cannot send session cache limiter - headers already sent (output started at /home/krecik/public_html/silnik.php:208) in...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
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: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
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...
0
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...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.