Deep understanding of C series: Relationships between variable names and memory of Different Types

Source: Internet
Author: User
Tags define null

With the basis of the previous two articles, the following describes the relationship between variable names and memory. Let's take a look at the code that everyone is familiar:

  int i;  scanf_s("%d", &i);

Int I;, the memory is allocated to I in this sentence (but this memory has not been initialized), so you can use this memory directly through & I. Assign values, not to mention I = 3 ;.

  Variable name I is used for convenience by programmers. It is the alias of this memory and refers to block memory, for programmers, I represents the value stored in this memory (actually I refers to this memory and then the value ). Generally, we use known memory through variable names.

IRepresentative(Stored in this memory)Value, while& IRepresentative(This memory)Address. The program itself is notIThis variable name allocates space.In the final machine code, there is no variable name, which can be seen in the analysis of the disassembly language (command: dumpbin/disasm XX. OBJ> xx_disasm.asm can view the disassembly language ). How does the compiler process the variable name? The variable name is stored in the symbol table and the index in the symbol table is mapped to the actual physical space (Address). When this variable is called, you can find the corresponding address and set the value to the symbol table.

 

The above analyzes the variable names of basic data types (such as int and char. In addition to variable names, C also includes function names, constant names, pointer names, array names, and structure names. Unlike variable names, these identifiers correspond directly to addresses. For a variable of the basic data type, the correspondence between the variable and the address needs to take the address & to get the address, while for other variables, the name itself corresponds to the address.

For example, char * Pc = "se"; that is, assign the first address (in the constant storage area) of the String constant "se" to the character pointer PC. This explains why you can assign a value to a PC without having to assign an address, instead of encountering a wild pointer problem similar to the following code:

  int *pi;  *pi = 1;

An int * PI sentence allocates space for pi instead of opening up the space pointed to by Pi.

 

The following describes the relationship between variable names and memory of different types:

First lookCConstant in:

How does C handle constants? For example, the constant 3 in I = 3; above, the address for storing the constant 3 is not randomly allocated and is in the Data Segment of the program.(. Data?I am not sure about this either. I hope the elders can give me some guidance.),That is, the program itself does not allocate memory for 3, but directly writes commands.. 3 is a numeric constant. How does one deal with character constants and string constants?

  Character constants and numeric constants are the same processing method., AllSimilar to the immediate number in the Assembly, directly write the command;

String constants are stored in the constant storage area,You can use & ("string") to obtain the specific address. That isThe String constant name is an address., But cannot be directly operated (the same as I in int I ).

 

Let's look at the names of various types of variables,CInData TypeExcept ConstantsRoughYes5Type:

Basic data types: int, float, double, Char, etc:

  The names of the variables for each basic data type and the processing method for declaring them are the same. When declaring them, the memory is allocated and the variable name is used to directly operate the memory; use the address symbol and the number to get the address. If you do not need to initialize the declaration, check whether it is a global variable or a static variable.

This type of variable name points to an address space, but it cannot be used directly as an address, but is operated through the address operator.

 

Construct Data Types: array, structure, and union:

1) array

When the array is declared, space is allocated:

   int a[5];

Once a [5] is declared, it is equivalent to six variable names: A, a [0], a [1], a [2], a [3], and a [4. The reference method of a [I] is the same as that of int I, which indicates a corresponding memory space;The key is the variable name.AAnd can be used as an address. We knowAIs the array name,AIt does not represent the address of the entire array, but points to the address of the first element of the array (although the values are the same, we will explain it in detail below ).Int * P =;. So how does & A explain it? For int I, I represents a space, & I represents the space address represented by I;So&It should also indicateAThe address, that is, the address of the entire array.

A, & A, and & A [0] are the same addresses, and because arrays are stored sequentially, therefore, the addresses represented by a, & A, and & A [0] are the same in data, but the actual meanings are different:

  • A is an int * type data, which is equivalent to & (* A) and the address pointing to the first element of the array;
  • & A refers to the entire array, which is an int (*) [] type data and the address of the pointer array;
  • & A [0] indicates only one space for storing the int type, which is int * type data.

That is, the array name, which can be used as an address, refers to the address of the first element of the structure.

2) Structure

When the structure is declared, space is allocated.Struct and array are different. Variable names of struct types cannot be directly used as addresses, which is the same as basic data types.The structure name must use the accessor & to perform the address operation, and the obtained address representsPointer to structOnly the addresses of the first element in the data and struct are the same.

For each element in the struct, The ing relationship of its name is the same as its data type, and is not affected because it is a struct element. For details, see the following code:

Struct Stu {int age; char sex; char * Name; int score [5] ;}; int main () {int I; struct Stu ST1; // ST1 is the struct Stu type printf ("% d \ n", & ST1); // & ST1 is the Stu * type printf ("% d \ n ", & st1.age); // & st1.age is of the int type *, and st1.age is of the int type. The name points to the address, but cannot be used as the address directly.
Printf ("% d \ n", & st1.sex); // & st1.sex is of the char * type, and the name is parsed in the same way as printf ("% d \ n", & st1.name ); // & st1.name is Char ** type, st1.name is char * type printf ("% d \ n", st1.score); // st1.score is an array type, the name represents the address of the first element in the array. Return 0 ;}

 

3) combination:Union is a special struct. To save space, each element is stored in sequence. The first address of each element is offset from the base address of the variable to 0, the Analysis and struct of specific variable names are the same.

 

Pointer type

Declaring a pointer type int * P; allocates space for the storage pointer P, and does not perform any action for the memory pointed to by P, which is the reason for the wild pointer. As shown in the following code, P is a pointer that does not point to any known memory. If you assign a value to * P, an error will naturally occur:

  int *p;  *p = 1;

Pointer,Char*Is a special pointer.. Generally, pointers only point to a defined type of memory, whileChar * can point to a string. The reason for this function is that the existence of the string ending character '\ 0' marks the end of the string.The following code points the PC to the constant store address referred to by "string.

  char *pc = “string”;

This is also the reason why char * Pc = "string" is legal, and int * p = 1 is invalid: "string" itself represents its storage address, the integer constant 1 is only an operand, not an address. If you want to assign a value to the pointer (pointing address), you can use a forced conversion int * P = (int *) 1, however, if you do not check the code, the written code may have security risks. Therefore, whether the pointer variable is global, local, static, or non-static, it should be declared for initialization at the same time, either to a valid address or to null.

In addition, declaring a pointer only allocates an address for the pointer's storage in the stack area, it does not limit whether the memory pointed to by the pointer is in the stack area, in the heap area, or in the constant storage area.This causesFunction call Return ValueDifferent implementations have different meanings, which is the reason why the return value is different after the function call is completed.For details, see extract pointer and address from string.

 

Null type

  C has the void keyword, but in fact there is no empty type in C.For example, we cannot define the following:

    void a;

  Because C and C ++ are static languages, memory is allocated when variables are defined.However, variables of different types occupy different memory. If a variable of any type is defined, the memory cannot be allocated to it. Therefore, no variable of any type exists in C and C ++.

However, it is valid to define void * P,The P defined by void * Indicates a pointer, And the type to which it points is not fixed. Because void * P; The Declaration allocates space for the pointer P. No matter what type the Pointer Points to, the space required for storing the pointer is fixed, therefore, there is no problem that the space cannot be allocated to P due to the size of the required space.

However, the use of void * P is also very limited. because you do not know the data type it points to, you cannot perform auto-increment operations on p. void has two main functions, one is to restrict the return value of a function, the other is to restrict the parameter type of a function, and void * is often used for pointer type conversion. The following code:

  int *pi;  float *pf;

If you want to point pi to the memory space pointed to by PF, you must perform type conversion: Pi = (int *) PF ;.

If you want to change pi to void * P, you do not need to convert it. You can assign a value to the pointer directly. This direct value assignment can only assign a pointer of a known type to void * P, instead of assigning a value to a pointer of a known type without the enhanced conversion of void * P, for example:

Void * P; int * PI; float * PF; P = PF; // pF = P; it is invalid, the value of the "Void *" type cannot be allocated to the object P = pI of the "float *" type;

  However, even if the conversion is performed, P is still a void * type pointer and cannot be sizeof (p) or other operations involving the specified type, similarly, P cannot be used directly for operations of specific data types.* P = 1.73; and printf ("% F", * P) are invalid in the following code:

Void * P; float * PF; P = PF;
* P = 1.73; // * pF = 1.73; valid printf ("% F", * P); // printf ("% F", * PF); valid

So what is the significance of void? You can use forced type conversion to use void * P as the intermediary. See the following code:

  float *pf;  void *p;  float f=1.6;  p = (void*)&f;  pf = (float*)p;

In this way, float * pf points to the address where float F is located, but note that P still cannot be used directly. This example shows that void * has such a function, but it is rarely converted in normal code,More importantly, void * is used as the function parameter to accept any type of pointer.Typical memory operation functions such as memcpy and memset are as follows:

  void * memcpy(void *dest, const void *src, size_t len);  void * memset ( void * buffer, int c, size_t num );

You can also compile a function that uses void * as the function parameter. Because char is the minimum length variable in C, the length of any other variable is an integer multiple of it. Char * can be used as a transit function. For details, see the following function implementation:

void swap(void *pvData1, void *pvData2, int iDataSize){    unsigned char  *pcData1 = NULL;    unsigned char  *pcData2 = NULL;    unsigned char  ucTmp1;    pcData1 = (unsigned char *)pvData1;    pcData2 = (unsigned char *)pvData2;       do{        ucTmp1       = *pcData1;        *pcData1     = *pcData2;        *pcData2     = ucTmp1;        pcData1++;        pcData2++;    } while (--iDataSize > 0);}int main(){         float fa = 1.23, fb = 2.32;         float *f1=&fa, *f2=&fb;         int iDataSize = sizeof(float)/sizeof(char);
swap(f1, f2, iDataSize); return 0;}

 

Null

C has two predefined meanings of null:

  #define NULL    0  #define NULL    ((void *)0)

In addition, standard C stipulates that, during initialization, assignment, or comparison, if one side is a variable or pointer expression, the compiler can determine that the constant 0 on the other side is a null pointer, and generate the correct NULL pointer value. That is, in the pointer context, "an integer constant expression with a value of 0" is converted to a null pointer during compilation. That is, the two definitions above are consistent in the pointer context.

When we declare a pointer, the null value in int * Pi = NULL, which is commonly used to avoid wild pointers, is automatically converted to (void *) 0. The following code is also valid:

int *pi = 0;if(pi == 0){ …… }

 

Function Type and function pointer

  Although the function is not a variable, it still has its physical address in the memory. Each function has an entry address. The function name points to this entry address. The function name is equivalent to a pointer constant pointing to its function entry.

You can assign a function name to a pointer so that the Pointer Points to the function entry, that is, the functionPointer.

Note that the pointer function is distinguished here:

PointerFunctionIs a function that returns pointers. the pointer function is defined as follows:

Char*Convert (char * pname, int length );

  The function pointer must be defined in the same way as the function to which it points.For example, define a function pointer for the int max (int A, int B) function:

  int (*pMax)(int a, int b);  pMax = Max;

Int(* Pmax)In a (int A, int B) sentence, brackets outside the function pointer Pmax must carry [S1], because "()" has a higher priority than "*". If no parentheses exist, it becomes Int.* Pmax(Int A, int B) is a declaration of a function (pointer function. The Pmax = max clause will represent the function name Max of the int max (int A, int B) Entry address, which is assigned to the pointer Pmax pointing to the same type of function. In this way, Pmax has the same reference function as Max, and Pmax can also point to a function with the same parameters as int max (int A, int B) and return values.

Int max (int A, int B); int min (int A, int B );
INT (* p) (int A, int B); int Max, min; P = max; max = (* p) (3, 5); // when calling, remember to include brackets (* P) P = min; min = (* p) (3, 5)

In the execution, point P to the pointer:

 

Note that,Because the distribution of functions in the memory is not neat, the function pointer does not have the ++ auto-increment or-auto-subtraction operations.

 [S1]

Using parentheses to forcibly combine Pmax with "*" means that Pmax is a pointer. Then, it is combined with "()", indicating that the pointer points to a function, then it is combined with the previous int, that is, the return value of this function is int. It can be seen that pfun is a pointer to a function whose return value is int.

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.