Code Review: Structures

  • Thread starter Vijay Kumar R Zanvar
  • Start date
V

Vijay Kumar R Zanvar

Hi c.l.c,

The following table show the general structure
of a header:

Byte # Field Description
------ -----------------

0 Extended message flag (01H)
1 Extended message length (n)
2 Extended message code
3-(n+1) Optional arguments


Multibyte fields are specified in big-endian order.
Now, I can declare the structures in two ways:

struct header_1 {
unsigned char flag;
unsigned char len;
unsigned char code;
char *arg;
};

and,

/* 32-bit m/c. i.e., sizeof (int) == 4 */
struct header_2 {
unsigned int flag : CHAR_BIT;
unsigned int len : CHAR_BIT;
unsigned int code : CHAR_BIT;
char *arg;
};


My major concern are padding, sizeof the structures and
speed of execution. Are the two structures the same in this
regard?
 
R

Richard Bos

Vijay Kumar R Zanvar said:
struct header_1 {
unsigned char flag;
unsigned char len;
unsigned char code;
char *arg;
};

and,

/* 32-bit m/c. i.e., sizeof (int) == 4 */
struct header_2 {
unsigned int flag : CHAR_BIT;
unsigned int len : CHAR_BIT;
unsigned int code : CHAR_BIT;
char *arg;
};


My major concern are padding, sizeof the structures and
speed of execution. Are the two structures the same in this
regard?

That's an unanswerable question; the Standard leaves padding free,
especially with bitfields. The only way to get an answer is test, and be
aware that your test is only valid for your compiler, perhaps not for
others.
Personally, I'd use the first one, not for any reasons of efficiency,
but because it's clearer.

Richard
 
V

Vijay Kumar R Zanvar

I have one more question:

/* struct_header.c */

struct header_3 {
unsigned char reserved_1 : 5;
unsigned char lun : 3;
};

#gcc struct_header.c -ansi -Wall -pedantic
struct_header.c:23: warning: bit-field `reserved_1' type invalid in ISO C
struct_header.c:24: warning: bit-field `lun' type invalid in ISO C


Does that mean we can not use char type for bit-fields? If so, why?
 
E

EventHelix.com

Multibyte fields are specified in big-endian order.
Now, I can declare the structures in two ways:

struct header_1 {
unsigned char flag;
unsigned char len;
unsigned char code;
char *arg;
};

and,

/* 32-bit m/c. i.e., sizeof (int) == 4 */
struct header_2 {
unsigned int flag : CHAR_BIT;
unsigned int len : CHAR_BIT;
unsigned int code : CHAR_BIT;
char *arg;
};


My major concern are padding, sizeof the structures and
speed of execution. Are the two structures the same in this
regard?

Prefer using the structure with char declarations. Use of bit fields
is not very portable. Also, you should check the actual layout
of the structure in memory. It is quite likely that the compiler
has introduced padding before the "char *arg" parameter.

Also checkout the following article:

http://www.eventhelix.com/RealtimeMantra/ByteAlignmentAndOrdering.htm

Sandeep
 
R

Richard Bos

Vijay Kumar R Zanvar said:
struct header_3 {
unsigned char reserved_1 : 5;
unsigned char lun : 3;
};

struct_header.c:23: warning: bit-field `reserved_1' type invalid in ISO C
struct_header.c:24: warning: bit-field `lun' type invalid in ISO C

Does that mean we can not use char type for bit-fields?

It does. Only _Bool, signed int, unsigned int, or qualified versions of
those (and, presumably, typedef'ed equivalents)
If so, why?

No idea. Can't find it in the Rationale, either.

Richard
 
C

CBFalconer

Vijay said:
I have one more question:

/* struct_header.c */

struct header_3 {
unsigned char reserved_1 : 5;
unsigned char lun : 3;
};

#gcc struct_header.c -ansi -Wall -pedantic
struct_header.c:23: warning: bit-field `reserved_1' type invalid in ISO C
struct_header.c:24: warning: bit-field `lun' type invalid in ISO C

Does that mean we can not use char type for bit-fields? If so, why?

Because it is neither an int nor an unsigned int.
 
B

Barry Schwarz

Hi c.l.c,

The following table show the general structure
of a header:

Byte # Field Description
------ -----------------

0 Extended message flag (01H)
1 Extended message length (n)
2 Extended message code
3-(n+1) Optional arguments


Multibyte fields are specified in big-endian order.
Now, I can declare the structures in two ways:

struct header_1 {
unsigned char flag;
unsigned char len;
unsigned char code;
char *arg;

In addition to the issues raised in other responses, I don't think you
can use arg this way if the header is something you read or write. E.
g., if you read the header from a file into an object of type struct
header_1, the bytes following code (if any) will contain the optional
arguments, not the address of these arguments.
};

and,

/* 32-bit m/c. i.e., sizeof (int) == 4 */
struct header_2 {
unsigned int flag : CHAR_BIT;
unsigned int len : CHAR_BIT;
unsigned int code : CHAR_BIT;
char *arg;
};


My major concern are padding, sizeof the structures and
speed of execution. Are the two structures the same in this
regard?



<<Remove the del for email>>
 
J

Jack Klein

I have one more question:

/* struct_header.c */

struct header_3 {
unsigned char reserved_1 : 5;
unsigned char lun : 3;
};

#gcc struct_header.c -ansi -Wall -pedantic
struct_header.c:23: warning: bit-field `reserved_1' type invalid in ISO C
struct_header.c:24: warning: bit-field `lun' type invalid in ISO C


Does that mean we can not use char type for bit-fields? If so, why?

C99 adds the _Bool type to int and unsigned int. It also allows, but
does not require, an implementation to accept other
implementation-defined types. So the only allowed types prior to C99
are signed and unsigned int, and the only guaranteed portable ones
even in a C99 conforming implementation are those two and _Bool.
 
A

Anupam

Vijay Kumar R Zanvar said:
Hi c.l.c,

The following table show the general structure
of a header:

Byte # Field Description
------ -----------------

0 Extended message flag (01H)
1 Extended message length (n)
2 Extended message code
3-(n+1) Optional arguments
Which means that bytes number 3 to n+1 are to contain certain values
in sequential memory locations. Do you depend on the sequential
ordering of these bytes? Then you are in a fix.
Multibyte fields are specified in big-endian order.
Now, I can declare the structures in two ways:

struct header_1 {
unsigned char flag;
unsigned char len;
unsigned char code;
char *arg;
};

Uh oh, that could be wrong. Presumably you will be malloc'ing the
(n+1)-3+1 bytes later. This means that the 3rd byte of the above
struct contains and address and bytes 4 through n+1 contain
uninitialised information.
This is right only if you are reading in the header and providing
specific code to move the bytes from 3 onwards to the correct
location.
and,

/* 32-bit m/c. i.e., sizeof (int) == 4 */
struct header_2 {
unsigned int flag : CHAR_BIT;
unsigned int len : CHAR_BIT;
unsigned int code : CHAR_BIT;
char *arg;
};


My major concern are padding, sizeof the structures and
speed of execution. Are the two structures the same in this
regard?
Thats beyond the purview of the C standard. Still for all practical
purposes it should be so except for pathological cases such as a 9
byte char.
 

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

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top