A detailed explanation of the member variable migration problem in C language structure _c language

Source: Internet
Author: User
Tags function prototype

The position deviation principle of the structure body in C language simple, but often forget, make some notes to be a good way to remember

There are three principles:

A. All members in a struct whose first address offset must be an integer of the length of the data type, in which the first address of a member is offset by 0,

For example, if the second member type is int, the first address offset must be a multiple of 4, otherwise the "header fill" is required;

B. Total number of bytes in the structure the value returned by the sizeof () function must be an integer multiple of the length of the maximum member, otherwise the end padding is to be done;

C. If struct A has the structure body B as its member, then the offset of the first address of the structure B store must be an integer multiple of the maximum length of the member data contained in B.

If the member in B is Int,double,char, the offset of B should be an integer multiple of 8, otherwise the middle fill.

I believe everyone in the C language Program development process must have used the structure, then I do not know how you are in the structure of the member variable offset this piece is how to understand? This article will share with you, I recently on the C language in the structure of the migration of some of the thinking and summary.

Example 1

Let's define the requirements first:

The known structure body types are defined as follows:

struct node_t{
 char A;
 int b;
 int c;
};

And the structure is 1Byte aligned

#pragma packs (1)

Please:

Structure body struct The offset of member variable C in node_t.

Note: The offset here refers to the offset from the starting position of the structure body.

When I see this problem, I believe that the solutions that emerge in different human brains may vary, and here are some possible ways to solve these problems:

Method 1

If you are familiar with the library functions of C, then the first thing you think of is the Offsetof function (actually just a macro, let's call it that), we man 3 offsetof view the following function prototype:

 #include <stddef.h>

  size_t offsetof (type, member);

With this library function, we can do this with one line of code:

Offsetof (struct node_t, c);

Of course this is not the focus of this article, please read on.


Method 2

When we are unfamiliar with the library function of C language, do not worry at this time, we can still use our own method to solve the problem.

The most direct idea is: "The address of the struct member variable C" minus the "start address of the structure body"

Let's first define a struct variable node:

struct node_t node;

Then compute the offset of the member variable C:

(unsigned long) (& (NODE.C))-(unsigned long) (&node)

& (NODE.C) is the address of the struct member variable C and is forced to be converted to unsigned long;

The &node is the starting address of the structure body and is also forced into unsigned long;

Finally, we subtract the above two values and get the offset of the member variable C.

Method 3

According to Method 2, we can still get the offset of member variable C without the help of library function. But as programmers, we should be good at thinking, is it possible to make some improvements to the code above, so that our code can be more concise? Before making specific improvements, we should analyze what the problem is with Method 2.

Believe that I don't have to say more, careful you must have noticed, one of the main problems with Method 2 is that we've customized a struct variable node, and although we don't have any limitations on how to customize variables, we need to think about new solutions when we're faced with a problem where we don't allow custom variables.

Before exploring new solutions, let's explore a small problem with offsets:

Small problem

This is a simple geometric question, assuming that the shift from point A to point B in the coordinates, how to calculate b relative to a offset? The problem is very simple for us, and most people will blurt it out and get answers for b-a.

So is the answer completely accurate? The more rigorous you think is obviously not, because, when a is the coordinate origin is a=0, the above answer b-a directly simplified to B.

What does this little simple question have to do with us?

We combine method 2 with the idea and the little questions above, are not soon getting the following association:

(unsigned long) (& (NODE.C))-(unsigned long) (&node)

And

B-a
The idea of our little problem is that when a is the coordinate origin, the b-a is reduced to B, and then to our method 2, when node's memory address is 0 (&node==0), the above code can be simplified to:

(unsigned long) (& (NODE.C))

Because the node memory address is ==0,

node.c  //struct body node member variable c

We can use another way to express the following:

((struct node_t *) 0)->c

The above code should be better understood, because we know the structure of the memory address number 0, so we can directly through the memory address to access the structure of the member variable, the corresponding code meaning is to get the memory address number 0 of the structure struct node_t member variable c.

Note: Here only uses the compiler's characteristics to compute the structure offset, does not have any operation to the memory address 0, some students may still have some questions, the detailed understanding this question may refer to the C language Structure member variable access way ponder.

At this point, our offset method eliminates the custom variable struct node_t node, which is directly one line of code to solve:

(unsigned long) (& (((struct node_t *) 0)->c))

The above code is a little more concise than Method 2.

Here we define the above code function as a macro that is used to compute the offset of a member variable in a struct (the following example uses the macro):

#define OFFSET_OF (Type, member) (unsigned long) (& ((type *) 0)->member))

Using the macros above, you can directly get the offset of member variable C in the struct node_t of the struct body as follows:

Offset_of (struct node_t, c)

Example 2

As with Example 1, we first define the requirements as follows:

The known structure body types are defined as follows:

struct node_t{
 char A;
 int b;
 int c;
};

int *p_c, which points to the member variable C of struct node_t x

1Byte alignment of structural body

#pragma packs (1)
Please:

The value of the member variable B of the struct body x?

To get this problem, we first do a simple analysis, the meaning of the topic is based on a pointer to a struct member variable, how to find the structure of another member variable value.

Then there are several possible solutions:

Method 1

Since we know that the structure is 1Byte aligned, the simplest solution to this problem is:

* (int *) ((unsigned long) p_c-sizeof (int))
The above code is very simple, the address of member variable C minus sizeof (int) to get the address of member variable B, and then cast to int *, finally take the value finally get the value of member variable B;

Method 2

The code for Method 1, though simple, is not very scalable. We hope to get the pointer p_node to the structure directly through P_c, and then access any member variables of the structure through P_node.

Thus we get the idea of calculating the starting address p_node of the structure body:

"Member variable C's address P_c" minus "C offset in struct body"

By Example 1, we get the offset of member variable C in struct struct node_t as:

(unsigned long) & (((struct node_t *) 0)->c)

So we get the starting address pointer p_node of the struct body as:

(Struct node_t *) ((unsigned long) p_c-(unsigned Long) (& ((struct node_t *) 0)->c))

We can also directly use the OFFSET_OF macro defined in Example 1, the above code becomes:

(Struct node_t *) ((unsigned long) p_c-offset_of (struct node_t, c))

Finally, we can use the following code to get the value of the member variable a,b:

P_node->a

P_node->b

We also define the functionality of the above code as the following macro:

#define Struct_entry (PTR, type, member) (type *) (unsigned long) (PTR)-offset_of (type, member)
The function of the macro is to obtain a pointer to the struct body by using a pointer to any member variable of the struct.

We use the macros above to modify the previous code as follows:

Struct_entry (P_c, STRUCT node_t, C)

The P_c is a pointer to the struct NODE_T member variable C of the structure body;

struct node_t structural body type;

C is the member variable that the P_c points to;

Note:

Some instructions about address operations in the preceding example:

int a = ten;
int * P_a = &a;

Set

P_a = = 0x95734104;

The following are the results of the compiler calculation:

P_a + = = p_a + sizeof (int) *10 =0x95734104 + 4*10 = 0x95734144

(unsigned long) p_a + = 0x95734104+10 = 0x95734114

(char *) p_a + = = 0x95734104 + sizeof (char) *10 = 0x95734114

From the above three kinds of situations, I believe you should be able to understand what I want to express the meaning. (Note: A subsequent blog post will elaborate on this issue from the compiler's perspective)

Conclusion

This article describes some of the interesting things about migration from the C language structure through a few examples, hopefully it will help you. Why there is such thinking, I believe some students have seen some clues, this is the follow-up blog will be described in the theme.

If there are errors in the article, please note that.

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.