About VA and byte alignment

Source: Internet
Author: User

This is an example program that uses variable function parameters, as shown below:
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
// # Include <stdarg. h>

Typedef char * va_list;

// # DEFINE _ intsizeof (N) (sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
// # Define
Va_start
(AP, V) (AP = (va_list) & V + _ intsizeof (v ))
// # Define va_arg (AP, t) (* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t )))
// # Define va_end (AP) (AP = (va_list) 0)

VoidVa_start
(Char * var_arg, int n_values)
{
Int I = (sizeof (n_values) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 );
Var_arg = (char *) & n_values + I;
}

Template <class T>
T va_arg (char * var_arg, t arg_kind)
{
Int I = (sizeof (t) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 );
Return * (T *) (var_arg + = I)-I );
}

Void va_end (char * var_arg)
{
Var_arg = (char *) 0;
}

Float
Average (INT n_values ,...)
{
Char * var_arg;
Intcount;
Floatsum = 0;
Int int_kind;

/*
** Prepare to access the variable arguments.
*/
Va_start
(Var_arg, n_values );

/*
** Add the values from the variable argument list.
*/
For (COUNT = 0; count <n_values; count + = 1)
{
Sum + = va_arg (var_arg, int_kind );
}

/*
** Done processing variable arguments.
*/
Va_end (var_arg );

Return sum/n_values;
}

Void main (void)
{
Float a = average (2, 1, 3 );
Printf ("A = % F/N", );
Return;
}

We know that the function using variable parameters must contain stdarg. h file, mainly used in the X86 platform stdarg. the following parts of the H file (copying them directly to the program can omit stdarg. h file inclusion ):
Typedef char * va_list;

# DEFINE _ intsizeof (N) (sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
# DefineVa_start
(AP, V) (AP = (va_list) & V + _ intsizeof (v ))
# Define va_arg (AP, t) (* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t )))
# Define va_end (AP) (AP = (va_list) 0)
To understand these macro definitions, I commented them out in the example program and added three functions (this way we can perform tracing debugging, but the macro definition won't work ):
VoidVa_start
(Char * var_arg, int n_values );
T va_arg (char * var_arg, t arg_kind );
Void va_end (char * var_arg );

This example program can be compiled, but an error occurs during running.

Let me see why? Or explain the macro definitions for me. Thank you!

Variable parameters!
Va_start
Specify the location of the first parameter
Va_arg get the parameter value (the type needs to be specified)
Va_end variable parameter acquisition

Variable parameters
Like the printf output function is a variable parameter function, it is used in function implementation.
Va_start
Specify the location of the first parameter
Va_arg get the parameter value (the type needs to be specified)
Va_end variable parameter acquisition

Va_start
Specify the location of the first parameter
Va_arg get the parameter value (the type needs to be specified)
Va_end variable parameter acquisition

Thank you. I know all this. What I want to ask is:
(Sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
For example, what does this sentence mean? In this way, when there is a similar problem and there is no ready-made solution (the predecessors have not done similar work), you can find a solution. At the same time, by parsing the C source code, we can learn from masters.

C/C ++ code
   
(Sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))

YesByte alignmentHere is the 32-bit alignment (32bit)

Upstairs, how can I see it is 32-bit alignment?
Note in stdarg. H that:
Note that for char, short is implicitly increased to int type, and float is implicitly increased to double type.

(Sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
In this example, 32-bit alignment is indicated, but 64-bit alignment is also supported.

I want to know why the Data Alignment function is implemented in this sentence. (If you want to convert the macro into a function for debugging, an exception occurs :-)

Guanzhu xuexi

You can find a number and calculate it with a pen. This alignment method is common in some original code.

Well, let me give you a detailed explanation. By the way, let's give my Variable Parameter notes a perfect ending :-)

The variable parameter is an application in which the called function operates the stack space directly.

The original operation macro does not change the stack space.
The function you defined modifies the stack space.

This is why the variable parameter operation in the "function" mode you changed is not available.

C/C ++ code
   #define _INTSIZEOF(n)  ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) 
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )

By carefully analyzing this definition, you will find that:

Pair pair _ intsizeof (n ):
In a 32-bit System (32-bit compiler), sizeof (INT) is 4, and this macro calculates 4Byte alignment
The number of bytes required to store N data.
Similar to other systems (corresponding compilers. You can analyze it by yourself.

PairVa_start
(AP, V ):
V is the first function parameter. The AP obtains the address of the adjacent parameter after (alignment) v.
In fact, the "first variable parameter" address is saved to the AP.

Callback to va_arg (AP, T ):
First + = the number of bytes required for the T-type data after alignment, then-the number of bytes, and then convert to the pointer value.
In other words, the * (T *) AP is returned, and then the AP is modified to the T-type data size.
In this case, the AP is the "next variable parameter" address.

⒋ Va_end is similar. You can analyze it by yourself.

Function implementation.
You can change the parameter transmission to the reference method.
On this basis, the variable parameter logic is implemented.
Goodluck

Byte alignment
Learning notes
I. Question proposal
I wrote a Variable Parameter Learning note two years ago, which I once briefly explained:
Code
(Sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
The role is to considerByte alignment
Calculate the starting address of the first variable parameter.
At that time, due to limited time and level, no more detailed explanation was made.
Today () I saw a post on the csdn forum.
Http://topic.csdn.net/u/20071123/16/c8d17d3f-9f49-49af-a6d8-1d7a7d84dc1c.html? Seed = 303711257
Problem: Variable Function Parameters in CRT source code analysis
Questioner: sun_moon_stars
I asked this macro again, so I decided to spend half a day explaining the problem in detail. That is my article.
Make a perfect ending.

II. Introduction
Let's first look at a problem in daily life,
Question 1: assume that we need to put a batch of goods in the container, and there are 12 items in the container,
A single box can hold a maximum of six goods, and the number of boxes is required.
Answer: Obviously we need 12/6 = 2 boxes, and each box is full. This is even for primary school students :-)

Question 2: change the condition of Question 1. If a box can hold up to five goods, what is the current number of boxes?
Answer: 12/5 = 2.4, but according to the actual situation, the number of boxes must be an integer. (If you do not know this knowledge, do not read it any more,
Re-reading in elementary school, huh, huh. Naturally, we need 3,
The following is a generalization of the problem.

Iii. General Mathematical Model
Question 3: A box can hold up to M pieces of goods, and N pieces of goods exist,
The minimum number of boxes is required and a general calculation formula is provided.
Note the following two points:
1. The total number of boxes must be an integer.
2. N is not necessarily greater than M. Obviously, even if n is less than m, a box is required.

Iv. General term formula
1. Prerequisites
Before answering question 3, let's clarify the meaning of the/operator.
Define/calculate as an integer operation, that is
For any two integers n and M, there must be and only a unique integer x, satisfying
X * m <= n <(x + 1) * M, N/m = x.
This is exactly the exact meaning of the/operation in C. For more information about the existence and uniqueness of X, see the number theory textbook.
If there is no additional description in the future, the meaning of the/operation is the same as that in the current section.

/Operations have a basic nature
If n = mx + Y, N/m = x + y/m.

Note: N cannot be split randomly. If n is set to a + B, N/m is not necessarily equal to A/m + B/M,
A and B must at least have a multiple of M.

2. Step-by-step discussion
According to the definition of the above/operator, we can get the answer to question 3, which will be discussed in detail.
If N/m = x is known
(1) When n is a multiple of M, that is, n = m * X, the number of boxes is X = N/m.
(2) If n is not a multiple of M, that is, when n = m * X + Y (1 <= Y <m)
Obviously, one more box is needed to hold the remaining y pieces of goods,
The total number of boxes is x + 1 = N/m + 1

3. General Formula
Although the above answers are complete, they are not convenient to use, because each time we determine the multiples of N and M,
We naturally need to think of a unified formula, so the following formula appears
Number of boxes: (n + M-1)/m

It is very easy to use a specific number to verify this formula, which is left for readers to do.
Here is a complete mathematical derivation:
Now we have assumed that the result of the/operation is an integer (or a modulo), that is
N/m = x, XM <= n <(x + 1) m
So,
(1) When n = Mx, (n + M-1)/m = mx/m + (M-1)/m = x
(2) When n = mx + Y (1 <= Y <m,
By 1 <= Y <m, coupled with the M-1, m <= Y-1 + M <= 2s-1 <2 m
According to/Operation definition (Y-1 + M)/m = 1

So (n + M-1)/m = (mx + Y + M-1)/m = mx/m + (Y + M-1)/m = x + 1
Obviously the formula (n + M-1)/m is consistent with the step-by-step discussion result in 2.
Some readers may also ask, this formula is how to come out, how to think of the plus that M-1?
To solve this problem, you can first look at the remainder theory in number theory.

V. Code Alignment Analysis
With the above mathematical foundation, let's take a look at the meaning of the alignment Code mentioned at the beginning.
(Sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
The meaning is obvious.
Here. The length of the machine word sizeof (INT) is equivalent to the capacity M of the box, and the actual size of the variable is
Total number of goods n, the entire code is to calculate the number of machines occupied by N.

By the way, explain it carefully.
~ (Sizeof (INT)-1 ))

Here we use a bit operation technique, that is, if M is a power of 2, then
N/m = N &(~ M-1 )),
This reader can use a specific number to verify this conclusion.
Here is a mathematical explanation:
If n and m are both binary numbers, and m is the power of 2, that is, M = power (2, y );
Then
N = m * x + z (1 <= Y <m)
Note that n, m, and Z are both binary representation, so the rightmost y digit of N is the remainder Z.
The remaining number on the left is the modulo X. Our task is to find out the modulo on the left.

Note:
(1) The most important point here is that m must be the power of 2 (Some people often think of it as a multiple of 2, which is wrong ),
Otherwise, the above conclusion is not true.
(2 )~ (M-1) more professional is called mask (mask ). Because after the number and the mask are operated and calculated, the rightmost y bit of the number
The number is 0 ("hidden"). That is, the number of digits in the rightmost 0 of the mask, and the number in the rightmost of the number is 0.

Summary:
1,Byte alignment
The essence of mathematics is the modulo operation in number theory. The meaning on the computer is to find the number of machine words occupied by an object.
2. In C, bitwise operations and masks can be used to accelerate the speed, provided that the length of the machine word must be a power of 2.

Ls is a caring uncle, pfpf

Paste

I will slightly change your program to meet the requirements for variable parameters.
Your main problem is that you use the value transfer method to be consistent with the standard macro call method. As a result, the storage method of variables in the stack is no longer what you think.
The program below is to change the value transfer to the address transfer on your foundation. I tried it and it should be okay to execute it. You can refer to it.
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>

Typedef char * va_list;

Float average (Int & n_values ,...);
VoidVa_start
(Char ** var_arg, Int & n_values );
Template <class T> T va_arg (char ** var_arg, t arg_kind );
Void va_end (char ** var_arg );

Int main (void)
{
Int ncount = 2;
Int ntemp1 = 1;
Int ntemp2 = 300;
Float faverage = average (ncount, ntemp1, ntemp2 );
Printf ("average = % F/N", faverage );
Return 0;
}

Float average (Int & n_values ,...)
{
Char * var_arg;
Int count;
Float sum = 0;
Int int_kind;

// Prepare to access the variable arguments.
Va_start
(& Var_arg, n_values );

// Add the values from the variable argument list.
For (COUNT = 0; count <n_values; count + = 1)
{
Sum + = va_arg (& var_arg, int_kind );
}

// Done processing variable arguments.
Va_end (& var_arg );

Return sum/n_values;
}

VoidVa_start
(Char ** var_arg, Int & n_values)
{
Int I = (sizeof (n_values) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 );
* Var_arg = (char *) & n_values-I;
}

Template <class T>
T va_arg (char ** var_arg, t arg_kind)
{
Int I = (sizeof (t) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 );
Return * (T *) (* var_arg-= I) + I );
}

Void va_end (char ** var_arg)
{
* Var_arg = (char *) 0;

}

By the way
Template <class T>
T va_arg (char ** var_arg, t arg_kind)
{
Int I = (sizeof (t) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 );
Return * (T *) (* var_arg-= I) + I );
}
* Var_arg-= I, which must be described as follows:
Because the method used to store variables in the environment is to store the Defined variables at the bottom of the stack, and then the Defined variables at the top of the stack, because ncount is the final definition, ntemp1, ntemp2 is on it, so it uses-= instead of the + =.

Haha, there are also information about int I = (sizeof (n_values) + sizeof (INT)-1 )&~ (Sizeof (INT)-1); analysis,
After reading the analysis of prawns upstairs, let me also share my opinion:

First, the standard macro definition of the Variable Parameter Function is to operate the stack directly. refer to the following code:
Double sum (INT Lim ,...)
{
Va_list AP; // declare object to hold arguments
Double tot = 0;
Int I;

Va_start
(AP, Lim); // initialize AP to argument list
For (I = 0; I <Lim; I ++)
TOT + = va_arg (AP, double); // access each item in argument list
Va_end (AP); // clean up

Return tot;
}
1) first create a parameter list AP, which is a struct pointer;
2) initialize the parameter list, whereVa_start
In (AP, Lim), lim not only specifies the number (secondary) of parameters in the Variable Parameter function, but also assigns its address to AP, so that it can operate on each operand in the stack (ideally, the Lim, and... parameters), but the problem is that the AP points to Lim, not the parameters we actually need.
Int I = (sizeof (n_values) + sizeof (INT)-1 )&~ (
Sizeof (INT)-1 );
It calculates the number of bytes occupied by LIM in the stack. Then, the AP offsets the positions of N to find the number of operations. not what the landlord saidByte alignment
.
I am only talking about what I mean, and I am inspired by reading this post today. If something is wrong, please point it out and study it together.

Classic, mark it

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.