Breadcrumbs


Subscribe RSS




It's time for new blog post, briefly about how to deal with implementing easy bit field structure layout in C :)

Let us see the following structure in C++

 

10 /*****************************************************************************

11 *

12 *    Splitt structure we are about to cast :)

13 *

14 *****************************************************************************/

15

16 // prototype C++

17

18 const int A_Flag_width = 2;

19 const int A_FrameID_width = 6;

20 const int A_Link_width = 8;

21 const int A_SplittID_width = 8;

22 const int A_Empty_width = 8;

23

24 typedef struct

25 {

26 DWORD32 A_Flag : A_Flag_width;

27 DWORD32 A_FrameID : A_FrameID_width;

28 DWORD32 A_Link: A_Link_width;

29 DWORD32 A_SplittID : A_SplittID_width;

30 DWORD32 A_Empty: A_Empty_width;

31 DWORD32 B_CRC;

32 char * Data;

33 }

34 splitt_struct;

35

36 /****************************************************************************/

It represents a recent structure I wanted to code in C about some Frame with header, which should be splitted in structure called Splitt, that has also some header and look like above declared. So to spare space you might wanna have precise bit layout. One way to deal nicely with bitlayouts are the bitfields like this (click), other way is to use bitsets (click), also few others using diverse libraries.

Anyway, enough said, the C variant is this:

 

39 /*****************************************************************************

40 *

41 *    This is the nice C variant :)

42 *

43 *****************************************************************************/

44

45 // define shit C

46

47 typedef char structure;

48 typedef structure * p_structure;

49

50

51 #define MEMBER_POINTER(number,t)                (t *)((p_structure)Example + number * sizeof(t))

52 #define MEMBER_VALUE(number,t)                    (*MEMBER_POINTER(number, t))

53

54 #define SUBMEMBER_CLEAR(member, t, start, end)    do { MEMBER_VALUE(member, t) &= ~(((SIZE_MAX << end) >> (end + start)) << start); } while (0);

55 #define SUBMEMBER_GET(member, t, start, end)    ((MEMBER_VALUE(member, t) << end) >> (end + start))

56 #define SUBMEMBER_SET(member, t, val, start, end) do { SUBMEMBER_CLEAR(member, t, start, end); MEMBER_VALUE(member, t) |= val << start ; } while (0);

57

58 #define MEMBER_LAST_BIT(t)                        (8 * sizeof(t) - 1)

59 #define END_OFFSET(t, end)                        (MEMBER_LAST_BIT(t) - end)

60

61

62 typedef structure Splitt;

63 typedef p_structure p_Splitt;

64

65 #define splitt Example

66

67 #define A                                        0

68 #define CRC                                        1

69 #define DATA                                    2

70

71 #define A_flag_start                            0

72 #define A_flag_end                                END_OFFSET(size_t, 1)

73 #define A_FID_start                                2

74 #define A_FID_end                                END_OFFSET(size_t, 7)

75 #define A_Link_start                            8

76 #define A_Link_end                                END_OFFSET(size_t, 15)

77 #define A_SID_start                                16

78 #define A_SID_end                                END_OFFSET(size_t, 23)

79 #define A_Empty_start                            24

80 #define A_Empty_end                                END_OFFSET(size_t, 31)

81

82 #define splitt_flag_get                            (SUBMEMBER_GET(A, DWORD32, A_flag_start, A_flag_end))

83 #define splitt_flag_set(val)                    SUBMEMBER_SET(A, DWORD32, val, A_flag_start, A_flag_end)

84 #define splitt_FID_get                            (SUBMEMBER_GET(A, DWORD32, A_FID_start, A_FID_end))

85 #define splitt_FID_set(val)                        SUBMEMBER_SET(A, DWORD32, val, A_FID_start, A_FID_end)

86 #define splitt_link_get                            (SUBMEMBER_GET(A, DWORD32, A_Link_start, A_Link_end))

87 #define splitt_link_set(val)                    SUBMEMBER_SET(A, DWORD32, val, A_Link_start, A_Link_end)

88 #define splitt_SID_get                            (SUBMEMBER_GET(A, DWORD32, A_SID_start, A_SID_end))

89 #define splitt_SID_set(val)                        SUBMEMBER_SET(A, DWORD32, val, A_SID_start, A_SID_end)

90 #define splitt_empty_get                        (SUBMEMBER_GET(A, DWORD32, A_Empty_start, A_Empty_end))

91 #define splitt_empty_set(val)                    SUBMEMBER_SET(A, DWORD32, val, A_Empty_start, A_Empty_end)

92

93 #define p_splitt_CRC                            (MEMBER_POINTER(CRC, DWORD32))

94 #define splitt_CRC                                (*p_splitt_CRC)

95

96 #define splitt_data                                MEMBER_POINTER(DATA, p_Splitt)

97

98

99 /****************************************************************************/

Nice :)

To explain briefly, I cast all to byte buffer and then use some shifting functions to extract different bit fields! (taking mask for example is pretty easy by shifting the other bits left and right to clear them). The code shown also forces using the name splitt for Splitt (e.g. you cannot use the functions after declaring "Splitt bubble")(I find this good).

What you can further do is to have the nice defines in "template style" way and then cast a multiple structures with the token pasting operator, which will make your code to look like the real deal! (I did it but then reduced the structures so it turned out to be obsolete)

You can also nest common headers with defines, which I also did with the structures later on (not shown, too much stuff)

Anyway, I don't intend to explain any further for now, just click to download the code with example test!