struct and union

Oct 29, 2009 at 2:49pm
we are using a struct and a union to map a 32bit microcode instruction to its corresponding bit fields. We have used this method before and it worked fine, except we did it in C++ before, and this one has to be in C.I've removed everything from the program except for the struct for testing purposes, and for some reasone it keeps telling me in Visual Studio:
error C2061: syntax error : identifier 'microFields'
or in Linux:
error: expected specifier-qualifier-list before 'microFields'
and
error: two or more data types in declaration specifiers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>


struct microFields
{
	unsigned int addr:9;
	unsigned int cond:2;
	unsigned int wr:1;
	unsigned int rd:1;
	unsigned int mar:1;
	unsigned int alu:3;
	unsigned int b:5;
	unsigned int a:5;
	unsigned int c:5;
};
union micro
{
	unsigned int microCode;
	microFields code;
};

int main(int argc, char* argv[])
{
	micro test;

	return 0;
} 


am i missing an include or something? The syntax is exactly what we used before, i can't figure out why it won't compile.
Oct 29, 2009 at 3:01pm
In C++, unions can only contain pointers.
Oct 30, 2009 at 2:47am
If I remember correctly, I thought you either had to typedef a struct/union or explicitly say what type it was, like this...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
typedef struct
{
	unsigned int addr:9;
	unsigned int cond:2;
	unsigned int wr:1;
	unsigned int rd:1;
	unsigned int mar:1;
	unsigned int alu:3;
	unsigned int b:5;
	unsigned int a:5;
	unsigned int c:5;
}microFields;

typedef union
{
	unsigned int microCode;
	microFields code;
}micro;

int main(int argc, char* argv[])
{
	micro test;

	return 0;
} 


If not, then you'd have to do something like this..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct microFields
{
	unsigned int addr:9;
	unsigned int cond:2;
	unsigned int wr:1;
	unsigned int rd:1;
	unsigned int mar:1;
	unsigned int alu:3;
	unsigned int b:5;
	unsigned int a:5;
	unsigned int c:5;
};
union micro
{
	unsigned int microCode;
	struct microFields code;
};

int main(int argc, char* argv[])
{
	union micro test;

	return 0;
} 


Try it... I might be wrong. I just had a midterm and my brain is tired!
Last edited on Oct 30, 2009 at 2:50am
Oct 30, 2009 at 2:54am
^That is only in C. In C++, it creates the typedef for you automatically.
Oct 30, 2009 at 4:13am
@pjwarez;

You can also do
1
2
3
4
typedef struct myStruct myStruct_t;

/* in main() */
    myStruct_t* pMyStruct;

but I think a simple
struct myStruct stMyStruct is more readable anyway.
Oct 30, 2009 at 12:30pm
 
myStruct stMyStruct;


is all that C++ requires. Prefixing with "struct" (or "union") is a requirement in C. In C++ it's just annoying.
Oct 30, 2009 at 1:06pm
Prefixing with "struct" (or "union") is a requirement in C. In C++ it's just annoying.


Yes... that's the whole point. In grcunning's original post, he's trying to compile some old code in C, not C++

grcunning
we did it in C++ before, and this one has to be in C


At least that what it looks like to me.
Oct 30, 2009 at 1:34pm
As yet, no one has mentioned that the thing the OP is trying to do is dangerous.

The order of bitfields in a structure, in both C and C++, is (you'd better sit down) not defined. That's right, upgrade your compiler and your program could break. The whole union thing is therefore a mistake.

You are much better off writing a couple of routines to encode and decode the bitfields:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
unsigned int micro_encode( struct microFields fields )
  {
  unsigned int result = 0;
  result |= (fields.addr & 0x1FF) << 23;
  result |= (fields.cond & 0x003) << 21;
  result |= (fields.wr   & 0x001) << 20;
  result |= (fields.rd   & 0x001) << 19;
  result |= (fields.mar  & 0x001) << 18;
  result |= (fields.alu  & 0x007) << 15;
  result |= (fields.b    & 0x01F) << 10;
  result |= (fields.a    & 0x01F) << 5;
  result |= (fields.c    & 0x01F);
  return result;
  }

struct microFields micro_decode( unsigned int code )
  {
  ...
  }

It costs you nothing more than a few lines of code and saves you against fragile code that will break with your next compiler upgrade, etc.

BTW, I don't know anything about microcode. I could very well have ordered the bitfields the wrong way in the above example. That's easy enough for you to fix.

Hope this helps.
Topic archived. No new replies allowed.