bit shifting as lvalue

J

jcitrix

Hi folks,

I'm looking at a problem that has been bugging me for a few days.
It's an forum question/problem that was posted by a reader and I can't
get my head around it. I've tried my due diligence to look this up
myself, but without knowing what the beast is I can't seem to form the
right query. So, now I'm here asking in hopes that the "human touch"
will prove more fruitful. Of course, I shudder to post anything to
c.l.c in fear of being called out as off topic. I certainly didn't
plan on that.

The code is to set up the global descriptor table for the x86
processor (but that's only details)...

Here's what I'm looking at (I've edited so I could get to the point):

struct Segdesc gdt[] =
{
[GD_KT >> 3] = yadda_yadda_yadda; /* this is the confusing
part */
};

/* what's with the bit shift on the left of the assignment operator??
my impression is 'undefined' or 'non-ISO'. */

struct Segdesc {
unsigned sd_lim_15_0 : 16; // Low bits of segment limit
unsigned sd_base_15_0 : 16; // Low bits of segment base address
unsigned sd_base_23_16 : 8; // Middle bits of segment base address
unsigned sd_type : 4; // Segment type (see STS_ constants)
unsigned sd_s : 1; // 0 = system, 1 = application
unsigned sd_dpl : 2; // Descriptor Privilege Level
unsigned sd_p : 1; // Present
unsigned sd_lim_19_16 : 4; // High bits of segment limit
unsigned sd_avl : 1; // Unused (available for software use)
unsigned sd_rsv1 : 1; // Reserved
unsigned sd_db : 1; // 0 = 16-bit segment, 1 = 32-bit
segment
unsigned sd_g : 1; // Granularity: limit scaled by 4K when
set
unsigned sd_base_31_24 : 8; // High bits of segment base address
};

If anyone can help me understand what the bit shift would do on the
left of an assignment (or point me in the direction of enlightenment)
I would be grateful. The OP in the forum said that this was an
"associated array type of structure". In Perl speak (<puts on flame-
retardant underwear>), this would be a hash, but that's not a
structure native to C and one would have to roll their own (or use a
third-party library)...

Or am I just totally off the reservation on this?

Cheers!
 
E

Eric Sosman

Hi folks,

I'm looking at a problem that has been bugging me for a few days.
It's an forum question/problem that was posted by a reader and I can't
get my head around it. I've tried my due diligence to look this up
myself, but without knowing what the beast is I can't seem to form the
right query. So, now I'm here asking in hopes that the "human touch"
will prove more fruitful. Of course, I shudder to post anything to
c.l.c in fear of being called out as off topic. I certainly didn't
plan on that.

The code is to set up the global descriptor table for the x86
processor (but that's only details)...

Here's what I'm looking at (I've edited so I could get to the point):

struct Segdesc gdt[] =
{
[GD_KT >> 3] = yadda_yadda_yadda; /* this is the confusing
part */
};

/* what's with the bit shift on the left of the assignment operator??
my impression is 'undefined' or 'non-ISO'. */

(Are you sure there's a semicolon after "yadda?" If
it's there I have no idea what's going on -- so I'll
assume it's not really there, and pretend that what *is*
there is either a comma or nothing at all.)

Notice the square brackets around the puzzling
expression. This is one of the new initializer forms
introduced in C99, one that lets you initialize
specific elements in an array. This C90 declaration

int array[] = { 0, 0, 0, 0, 1, 0, 0, 0, 0, 2 };

can be written in C99 as

int array[] = { [4] = 1, [9] = 2 };

(As in C90, any elements you don't mention receive zeroes.
And as in C90, the array size can be calculated from the
initializer list, but slightly differently: In C90 the
array is made large enough to hold as many initializers
as you write, while in C99 it holds the largest-mentioned
intialized element.)

In your example, GC_KT is presumably a macro that
expands to a compile-time constant -- let's suppose it's
twenty-four, so GC_KT >> 3 is three. Then you've got:

struct Segdesc gdt[] = { [3] = yadda };

.... which creates an array with four elements, initializes
elements [0], [1], and [2] to zeroes, and initializes the
final element [3] to yadda.
 
J

jcitrix

(Are you sure there's a semicolon after "yadda?" If
it's there I have no idea what's going on -- so I'll
assume it's not really there, and pretend that what *is*
there is either a comma or nothing at all.)

Yes, sorry, that semicolon was misplaced. I had been typing from
memory.
Notice the square brackets around the puzzling
expression. This is one of the new initializer forms
introduced in C99, one that lets you initialize
specific elements in an array. This C90 declaration

int array[] = { 0, 0, 0, 0, 1, 0, 0, 0, 0, 2 };

can be written in C99 as

int array[] = { [4] = 1, [9] = 2 };
[snip]

In your example, GC_KT is presumably a macro that
expands to a compile-time constant -- let's suppose it's
twenty-four, so GC_KT >> 3 is three. Then you've got:

struct Segdesc gdt[] = { [3] = yadda };

... which creates an array with four elements, initializes
elements [0], [1], and [2] to zeroes, and initializes the
final element [3] to yadda.

Yes, in this example GD_KT was a macro for 0x08 (the kernel table in
the GDT). The "yadda" part was a macro reference; the entire line
read: [GD_KT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 0) and was
followed by other GDT initialization code. The SEG macro was
#defineD:

#define SEG(type, base, lim, dpl) (struct Segdesc) \
{ ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \
type, 1, dpl, 1, (unsigned) (lim) >> 28, 0, 0, 1, 1, \
(unsigned) (base) >> 24 }

and I'm chewing on that now! :)

Thanks for your help Eric! I had been thinking to myself, "there's no
way this can work..." but (as you can see) I am unfamiliar with the
new additions in C99 (and to a large degree C90 as well). I will have
to work my way through the standard and try to digest as much as
possible. This was the first time I ran into a problem which required
knowledge of C99! Cool, yet frustrating!

Again, much gratitude!

-Sean
 
E

Eric Sosman

Yes, sorry, that semicolon was misplaced. I had been typing from
memory.

A point to ponder: When you're baffled by some syntactic
subtlety, are you in a good position to render the problem
faithfully "from memory?"

Hint, Hint, HINT for next time ...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top