Thread: Pointer to struct members

  1. #1
    Registered User
    Join Date
    Jul 2002
    Posts
    34

    Pointer to struct members

    Help... Due to the way the compiler lines up memory, i cannot assign member values using a pointer offset.


    typedefs used:
    BYTE is unsigned char(1 byte),
    UINT is unsigned short (2 bytes)

    Code:
    [.h]:
    typedef struct struct_System_Settings
    {
       BYTE    byTestBYTE2;
       UINT    nTestUINT1;
       BYTE    byTestBYTE3;
       BYTE    byTestBYTE4;
       UINT    nTestUINT2;
    
    }SYSTEM_SETTINGS;
    SYSTEM_SETTINGS *pSystemSettings; // global pointer
    
    // sizeof(SYSTEM_SETTINGS) returns 8 when it is actually 7 bytes, due to memory alignment ! arr....
    
    [.c]:
    
    // objective: plug values into the struct WITHOUT knowing the
    // member names (read from file, format <size in bytes><data>):
    
    for(;;)
    {
      // get data type (BYTE or UINT):
      if(fread(&byDataSize, 1, 1, pFile)==0)
         break; // end of file, complete
    
      // byDataSize: 1=BYTE, 2=UINT
    
      // get data:
      nData = 0;
      if(fread(&nData, byDataSize, 1, pFile)==0)
         break; // end of file, complete
    
      // copy to struct:
      if(byDataSize == 1)     // BYTE
         memmove((BYTE*)pSystemSettings + x, &nData, 1); // (BYTE = 1 Byte )	
      else                    // UINT
         memmove((BYTE*)pSystemSettings + x, &nData, 2); // (UINT = 2 Bytes)
    
      x += byDataSize;   // goto next member
    }
    
    // file read complete
    
    
    data read each time round the loop (all hex):
    
      byDataSize   |     nData    |  data type
    ---------------+--------------+------------
          01       |      F1      |   BYTE
          02       |      A1A1    |   UINT   <-- curruption here (nTestUINT1 is not = A1A1 !)
          01       |      F2      |   BYTE
          01       |      F3      |   BYTE
          02       |      A2A2    |   UINT
    coincedentally, if the struct size comes out as a even number of bytes, it works fine!

    Please help. There must be a way!

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    The real question is: Why bother? What's the point of assigning a value using memmove versus just an assignment? I really don't see the need or point in doing so. For starters, you're adding the unneeded overhead of calling a function, when an assignment would work just as well.

    I suppose if you need to mash an 'endian' into its reverse type, but still, an assignment would work just as well.

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jul 2002
    Posts
    34
    I'm using (wait for it...) visual c++ version 1.52 !! a dos compiler and 'c'.

    Unfortunatly, the exe is for an embedded application that can only run dos.

    The idea of just assigning the varibles directly is one that i have already toyed with:

    pointer -> member = value;

    It is indeed easier, but does not allow the program to be modified simply by editing the struct def.

    Having not been able to solve this problem, direct access seems to be the only way.

    joe
    #

  4. #4
    Registered User
    Join Date
    Jul 2002
    Posts
    34
    ah ha! so it does!!

    Cheers all.

    (going to use direct access now anyway)

    joe
    #

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I'm afraid I agree with Quzah. There's no point.

    It is indeed easier, but does not allow the program to be modified simply by editing the struct def.
    Why do you need to have a constantly changing struct definition??

    The #pragma pack() will align your data, but this is just putting a band aid over a very huge wound here. What are you trying to do exactly and why. C is very versatile and I'm sure there is a better way that works with C rather than against it.

    Quzah is right. Calling a function to do what can be done via assignment is........well, there are no words.

  6. #6
    Registered User
    Join Date
    Jul 2002
    Posts
    34
    Im not going to be moding this s/w once it is written. Someone else will have to do it.

    The structs are all loaded from files, the files are also written by a different win32 program, which is compiled using the "same" header file (so the structs are the same).


    I need to read data from a file into a struct, and dump the contents of the struct to a file. (load/save struct)

    In order to simplfy the mods to the program, i have a header file declairation of the struct.

    To add an extra member, all you have to do is mod the struct in the header file, all loading and saving functions should not need modifing.

    (almost like the W32 MFC "serialize" function, except the object is not created, just loaded)

    I have now acheived this, by using the following code:

    Code:
    [.h]
    #pragma pack(1)  // allow pointers to members, all members are butted
                     // up against each other, no internal alignment restrictions
                     // for members of different sizes.
    
      typedef struct struct_System_Settings
      {
         BYTE      byLangFileID;
         UINT      nScreenID_SCR2;
         BYTE      byFontID;
         BYTE      bySchemeID;
         UINT      nScreenID;
         INT       iScreenLoadResult;
         CHAR      cBeginChar;
         CHAR      cEndChar;
         UINT      nSC400_interupt_vect4;
      }SYSTEM_SETTINGS;
      SYSTEM_SETTINGS *pSystemSettings;
    #pragma pack()
    
    [.c]
    
    // load struct (assums that the # of bytes in the file is the same as sizeof(..) the struct:
    
       if(fread((BYTE*)pSystemSettings, sizeof(SYSTEM_SETTINGS), 1, pFile) == 0)
       {
          fclose(pFile);      // read error
          return FALSE;
       }
       fclose(pFile);
    
       // file loaded ok

    so you see, the code just reduces to nothing now i have worked out what was required.

    Only one function call (to read file), everything is read and assigned all at once. no need to decide weither the data type size is 1 byte or 99 bytes in size -- it no longer matters because the struct is alligned as a continous buffer.


    After-thought:

    Why does the compiler align (pack) stuff weird as default?





    joe
    #

  7. #7
    Registered User
    Join Date
    Jan 2003
    Posts
    648
    Originally posted by kybert
    Why does the compiler align (pack) stuff weird as default?
    I don't know what you're doing but I can answer that: a 32-bit compiler aligns things on 32-bit boundaries for optimun performance since a 32-bit computer can access memory in 32-bit offsets much faster than it can if its on another offset.

  8. #8
    Registered User
    Join Date
    Jul 2002
    Posts
    34
    Many thanks to all that helped me with this problem, I have finished writing the stuff i required and the problem is solved.


    Couldn't have done it without you guys... keep up the good work...

    (and i learned somthing new too!)


    Joe
    #

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  2. Replies: 1
    Last Post: 12-03-2008, 03:10 AM
  3. Struct Pointer Problems. (Warning: Long Post.)
    By Phoenix940 in forum C Programming
    Replies: 1
    Last Post: 11-30-2008, 10:04 PM
  4. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  5. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 06:58 PM