Use of structure (struct) to for a unique record

Folks,

There will be somone "out there" that will have the answer I'm seeking. At present I'm at a loss to find that answer.

I'm using a structure (struct) to greate a five byte field. The first byte is set at the bit level. The rest is an unsigned long field of four bytes.

I have put some trace statements in to try and track what is going on. Oddly enough, when I check the two fields, they come bask as having a size of 1 byte and 4 bytes. But, when I print the tag, it comes back with eith bytes - not five.

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 **************************************************************************
 *Program : DDS_20121217.cpp
 **************************************************************************
 */
#include <cstdlib>
#include <stdio.h>
#include <string.h>
#include <math.h>

// System Clock set as Hz.  User settable.
#define SysClk 18000000

// Scalar set as 2^32-1.  Special scalar defined by Scalar Devices (No pun).
#define MagicNum 0xFFFFFFFF

// Mega scalar (multiply by 1,000,000)
#define Mega *1000000

// -------------------------------------------------------------------------
// Define structures to be used
// ============================
struct ddscontrol
  {
    unsigned char SixTimesRefClk:1 ;	  //   D0   - Six Times (6x) Reference clock multiplier.
    unsigned char Parallel_Serial:1 ;	  //   D1   - Serial mode (active high).
    unsigned char Power_Down:1 ;		  //   D2   - Software power down (active high).
    unsigned char Phase_Shift:5 ;		  // D7..D3 - Not used with a single chip.
  } ;

struct ddsword
  {
    ddscontrol control ;		      	  // Control (one byte).
    unsigned long freq ;			      // Set Frequency (quad byte).
  } ;

// Assign sub-routines/functions to be used.
  void display( ddsword show ) ;

// -------------------------------------------------------------------------
// **** Core Program matter ****
// =============================
int main()
  {
    ddsword dds ;
    
    float  req_freq ;
    
    unsigned long
      ireq_freq ,
      iMagic ,
      iSysClk ,
      itestresult ;

  // Set up the DDS control byte
    dds.control.Phase_Shift     = 1 ;	  // 5-bit phase (D7..D3)
    dds.control.Power_Down      = 0 ;	  // 1-bit power down flag (D2).
    dds.control.Parallel_Serial = 0 ;	  // 1-bit serial/parallel load bit (D1).
    dds.control.SixTimesRefClk  = 1 ;	  // 1-bit 6x set bit (D0).

    printf( "SIZEOF( dds.control ) = %i \n", sizeof( dds.control ) ) ;
    printf( "SIZEOF( dds.freq ) = %i \n", sizeof( dds.freq ) ) ;
    printf( "SIZEOF( dds ) = %i \n\n", sizeof( dds ) ) ;

    printf( "dds.control = %02X\n\n" , dds.control ) ;

  // Request output frequency.
    printf( "Enter desired Frequency (MHz): ") ;
    scanf( "%f", &req_freq ) ;

  // Assign the defined values to working variables.
    ireq_freq = (unsigned long) req_freq*1000000 ;   // Convert to MHz to Hz.
    iSysClk = SysClk ;	                  // Save as Hz int variable.
    iMagic = MagicNum ;			          // Save as long integer variable.

    printf( "\n\nifrequency   = \t%10li Hz\n", ireq_freq ) ;
    printf( "System Clock = \t%10li Hz\n", iSysClk ) ;
    printf( "Magic Number = \t   0x%8lX \n\n", iMagic ) ;

    dds.freq = iMagic / iSysClk * ireq_freq ;
    printf( "dds.freq     = \t %7u\n\n", dds.freq ) ;

    printf( "SIZEOF( dds.freq ) = \t%i bytes\n\n", sizeof( dds.freq ) ) ;

    display( dds ) ; 

    system( "PAUSE" );

    return 0 ;
  } ;

// -------------------------------------------------------------------------
// **** Subroutines/Functions ****
// ===============================

// -- Display - Routine to display results (what else?)
void display( ddsword show )
  {
    int i ;
    
    printf( "SIZEOF( show ) = \t%i bytes\n\n", sizeof( show ) ) ;

	printf( "Complete 40-bit data\n" ) ;
	printf( "\tshow.control\t how.freq\n" ) ;
    printf( "\t%2X  \t %2X\n", show.control, show.freq ) ;
    printf( "\t%7i  \t %u \n\n", show.control, show.freq ) ;
    
    printf( "show.control = %i ", show.control ) ;
/*
    for ( i=39; i>=32; i-- )
      {
        if ( show.control & 1<<i ) printf( "1" ) ;
        else printf ( "0" ) ;
        if ( i%4 == 0 ) printf( " " ) ;
      };
*/
    for ( i=31; i>=0; i-- )
   	  {
        if ( show.freq & 1<<i ) printf( "1" ) ;
        else printf ( "0" ) ;
        if ( i%4 == 0 ) printf( " " ) ;
      };

    printf ( "\n" ) ;

  } ;


Generated output


SIZEOF( dds.control ) = 1
SIZEOF( dds.freq ) = 4
SIZEOF( dds ) = 8 <--- Should be 5 !!!

dds.control = 09

Enter desired Frequency (MHz): 10


ifrequency   =    10000000 Hz
System Clock =    18000000 Hz
Magic Number =     0xFFFFFFFF

dds.freq     =   2380000000

SIZEOF( dds.freq ) =    4 bytes

SIZEOF( show ) =        8 bytes  <--- should be 5 !!!

Complete 40-bit data
        show.control     how.freq
         9               8DDBEB00 <--- Hexidecimal notation
         9             2380000000 <--- Equvalent Decimal notation

show.control = 9 1000 1101 1101 1011 1110 1011 0000 0000
Press any key to continue . . . 


Any help in either the coding or understanding (or both) would be appreciated.

Rgds,
Nick
It took me a little while, but this was the best answer I've found so far (that also pertains to your use of bit fields and another data type): http://stackoverflow.com/questions/308364/c-bitfield-packing-with-bools

Reading up on bit fields (something I never was taught, or even knew existed), I learned that when using bitfields in a struct, as long as the total number of bits is less than or equal to the declared data type, uchar in your case, the size of that struct will be equal to the size of that data type. However, when you introduce a different data type in that struct (not sure if this only pertains to bit fields, need to do some more research), the compiler (typically implementation dependent) will try to line up the bits in the largest sized memory blocks, in your case, 4 byte blocks.

I might have misunderstood this, but it makes sense to me (aside from the fact that your one byte struct magically becomes 4). I don't effectively see a way around this (as of yet) but I'm going to keep doing some research to see if I can find something.

Thanks for posting, I have learned a lot today, and you've added a whole new level to that learning experience.

Edit: I also just stumbled upon this dealing with data alignment with structs in general (so it appears to apply to all data types, not just ones dealing with bit fields). http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member
Last edited on
The question is: why do you need it to be 5 bytes? Like, do you really need it?

Basically, the 8-byte size comes from compiler optimizations. It tries to align each member according to the alignment and packing requirements. You can control both of those using compiler directives. For MSVS you can look it up here:
http://msdn.microsoft.com/en-us/library/83ythb65.aspx
and here:
http://msdn.microsoft.com/en-us/library/2e70t5y1.aspx

So for your case, if you specify
#pragma pack(1)
before the structure declarations, you will get your 5-byte struct. It may decrease the performance though. So, again, the question is - do you really need it to be 5 bytes? If no - then just leave it to the compiler to generate the most optimal code.
Thanks Volatile Pulse and KRAkatau,

Volatile Pulse,

I read the linkVolatile Pulse provided - most informative but, it didn't quite cover what I was trying to achieve.

In itself, it did explain away the idiosyncrasies of C++ on various platforms.

I was brought up on a diet of Kerningham and Ritchie C. Yep when it was a type-writer written draft form. That was a lo-o-o-o-ng time ago.

As for "I have learned a lot today" - my pleasure. I figure that the day you stop learning - you're dead.

KRAkatau,

Thank you so very much. The #pragma statement was exactly what I needed. It works like a charm!!!

As for the statement/question;- "the question is - do you really need it to be 5 bytes?". Yep - sure do.

I need to generate a 40-bit string pattern (8-bit control word and 32-bit command) that will be read serially.

I’m working on a personal project that will be run by an ATMEL controller and some pretty fancy chips.

Bottom line need is simple - I was stuck!

With the aid of a simple question (with supporting code) and people on this forum, a lot of practical knowledge can be gained.

This was not a phising exercise. I am getting back into C/C++ coding. You will note that I categorize myself as a "Beginner".

I'd like to re-master the basics and I figure a "Beginners Forum" is one heck of a way to build that fundamental knowledge needed to get into the more serious stuff.

Many thanks to those that have contributed.

I trust that even this short thread will help others.

Regards,
Nick
Topic archived. No new replies allowed.