Usage of char data [0] In a variable-length array struct in C Language

Source: Internet
Author: User

Usage of char data [0] In a variable-length array struct in C Language

 

1. Structure memory layout (padding)

 

To make the CPU more comfortable to access variables, the storage addresses of member variables in struct have an alignment mechanism. This mechanism has two points in summary: first, the first address of each member variable must be an integer multiple of its type alignment value. If not, it must be filled with some meaningless bytes between it and the previous Member variable. Second, the size of the entire struct, it must be an integer multiple of the alignment value consumers in all the member types in the struct. If not, fill it after the last member.

The following typical alignments are valid for compilers from Microsoft, Borland, and GNU when compiling for 32-bit x86:

  • A char (one byte) will be 1-byte aligned.
  • A short (two bytes) will be 2-byte aligned.
  • An int (four bytes) will be 4-byte aligned.
  • A float (four bytes) will be 4-byte aligned.
  • A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on Linux.
  • A long double (twelve bytes) will be 4-byte aligned on Linux.
  • Any pointer (four bytes) will be 4-byte aligned on Linux. (eg: char *, int *)

    The only notable difference in alignment for a 64-bit linux system when compared to a 32 bit is:

    • A double (eight bytes) will be 8-byte aligned.
    • A long double (Sixteen bytes) will be 16-byte aligned.
    • Any pointer (eight bytes) will be 8-byte aligned.

       

      #include 
           
            #include 
            
             #include 
             
                struct s1        {                char ch,*ptr;                union                {                        short a,b;                        unsigned int c:2,d:1;                };                struct s1 *next;        };int main(){              printf("%d\n",sizeof(struct s1));        return 0;}
             
            
           

      Struct s1
      {
      Char ch, * ptr; // each of ch and * ptr occupies 2 bits, 4 bits in total
      Union // calculates the longest value, and the union occupies 4 bits.
      {
      Short a, B;
      Unsigned int c: 2, d: 1;
      }
      Struct * next; // pointer to struct, which occupies 8 bits in the same bytes as struct.
      }

       

      2. variable-length Array

      Abstract: In actual programming, we often need to use variable-length arrays, but the C language does not support variable-length arrays. In this case, we can use the struct method to implement a variable-length array in C language.

      Struct MyData
      {
      Int nLen;
      Char data [0];
      };

      In the structure, data is an array name, but the array does not have elements. The real address of the array follows the structure MyData, this address is the address of the data after the struct (if the content allocated to this struct is greater than the actual size of this struct, the additional part is the content of this data ); this declaration method can skillfully implement Array Extension in C language.
      The actual usage is as follows:
      Struct MyData * p = (struct MyData *) malloc (sizeof (struct MyData) + strlen (str ))
      In this way, you can use p-> data to operate this str.

       

      In this way, you can use p-> data to operate this str.

       

      Program instance:


      Struct MyData
      {
      Int nLen;
      Char data [0];
      };

      Int main ()
      {
      Int nLen = 10;
      Char str [10] = "123456789 ";

      Cout <"Size of MyData:" <
      MyData * myData = (MyData *) malloc (sizeof (MyData) + 10 );
      Memcpy (myData-> data, str, 10 );

      Cout <"myData's Data is:" <myData-> data <endl;

      Free (myData );

      Return 0;
      }

      Output:

      Size of MyData:
      4
      MyData "s Data is: 123456789

      From: http://bbs.chinaunix.net/thread-1455677-1-1.html

      I want to introduce a mistake I made in my project recently to show that I should be a real person, not a young man.
      In the code, I need to transmit data packets between a library and a daemon through socket. The package format is defined as follows (for simplicity, I will use the simplest data type as an example ):

      1. Typedef struct {
      2. Int head;
      3. Int size; // specify the length of the entire package
      4. Char reply;
      5. Char data [0];
      6. } Packet;
      7.  
      8. Packet * cmd = malloc (sizeof (packet) + 20 );
      9. Memcpy (packet-> data, some_data, 20); copy the code

        Daemon sends the above cmd package to the library. After receiving the package, the library needs to extract the data in the data field. Size indicates the length of the entire package, but no field indicates the length of the data. Do I need such a field to specify the data length? As a young man in B, I don't think it is necessary, so I calculate the data length as follows:

         

         

        1. # Define offsetof (type, element) (int) & (type *) 0)-> element)
        2. Static inline size_t packet_data_len (packet * cmd ){
        3. Assert (cmd );
        4. Return cmd-> size-offsetof (packet, data );
        5. }
        6.  
        7. Memcpy (buffer_to_receive_data, cmd-> data, packet_data_len (cmd); copy the code

          As a result, the success of this program has brought me countless bugs, inexplicable segfault, strange data errors, and some time to work properly. Of course, I finally found the problem:
          Sizeof (packet) = 12;
          This is reasonable. char reply is padded into four bytes, and char data [0] is 0 bytes.
          However, offsetof (packet, data) = 9. When calculating the offset, char reply is a byte without padding.
          Therefore, packet_data_len returns three more bytes each time than the actual data ......

          Finally, I added a data_len field to indicate the Data Length.

           

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.