Storage of C language data (integer and floating point) in memory

Table of contents

1. Basic classification of types

1.1 Integer

1.2 Floating point

1.3 Construction type

1.4 Pointer types

1.5 Empty types

2. Storage of integers in memory

2.1 Machine numbers and truth values

2.1.1 Number of machines

2.1.2 Truth value

2.2 Complement and inverse of original code

2.2.1 Original code

2.2.2 Inverse code

2.2.3 Complement code

2.2.4 Storage form of integer data

2.3 Big and small endian introduction

2.3.1 What is big endian and little endian

2.3.2 Why there is a big and small endian mode

2.3.3 The respective advantages of big and small endian storage

3. Storage of floating point numbers in memory

3.1 Examples of floating-point storage

3.2 Rules for storage of floating point numbers

3.2.1 Binary representation and decimal conversion of floating point numbers

3.2.2 IEEE 754 regulations

3.2.3 IEEE 754’s special regulations on significant digits M and exponent E:


1. Basic classification of types

1.1 Integer

char
        unsigned char
        signed char
short
        unsigned short [int]
        signed short [int]
int
        unsigned int
        signed int
long
        unsigned long [int]
        signed long [int]

1.2 Floating point

float
double

1.3 Construction type

> Array type
> Structure type struct
> Enumeration type enum
> Joint type union

1.4 Pointer types

int *pi;
char *pc;
float* pf;
void* pv;

1.5 Empty types

void means empty type (no type)
usually applied to function return type, function parameter, pointer type.

2. Storage of integers in memory

We know that to create a variable is to open up space in memory, and the size of the open space varies with different types. If you want to know how to store it, you must first know the following concepts.

2.1 Machine numbers and truth values

2.1.1 Number of machines

The binary representation of a number in a computer is called the machine number of the number. The machine number is signed, and the highest bit of a number is used to store the sign in the computer, the positive number is 0, and the negative number is 1.

For example, the number in decimal + 2, the computer word length is 8 bits, converted to binary is 00000010. If it is -2, it is 10000010.

Then, 00000011 and 10000011 here are the machine numbers.

2.1.2 Truth value

Because the first bit of the machine number is the sign bit, the machine number is not equal to the real value. For example, in the above signed number 10000010, the highest bit 1 represents negative, and its real value is -2 instead of the formal value 130 (10000011 converted to decimal equals 130). Therefore, for the sake of distinction, the real value corresponding to the machine number with the signed bit is called the real value of the machine number.

2.2 Complement and inverse of original code

There are three binary representation methods for integers in computers, namely original code, complement code and complement code (three forms of machine numbers).
The three representation methods all have two parts, the sign bit and the value bit. The sign bit uses 0 to represent "positive", and 1 to represent "negative"
. There are three different ways of representing negative integers.

2.2.1 Original code

The original code is the absolute value of the sign bit plus the true value , that is, the first bit is used to represent the sign, and the remaining bits represent the value. For example, if it is 8-bit binary:

  • The original code of +1: [0 (sign bit)]+[000 0001 (value bit)]=0000 0001;
  • The source code of -1: [1 (sign bit)]+[000 0001 (value bit)]=1000 0001;

2.2.2 Inverse code

The one’s complement of a positive number is itself; the one’s complement of a negative number is obtained by inverting the other bits on the basis of its original code without changing the sign bit.

  • [+1] = [0000 0001] original = [0000 0001] anti
  • [ -1] = [1000 0001] original = [1111 1110] anti

2.2.3 Complement code

The complement of a positive number is itself; the complement of a negative number is based on the original code, the sign bit remains unchanged, the rest of the bits are reversed, and finally +1. (That is, +1 on the basis of the inverse code)

  • [+1] = [0000 0001] original = [0000 0001] inverse = [0000 0001] complement
  • [-1] = [1000 0001] original = [1111 1110] inverse = [1111 1111] complement

2.2.4 Storage form of integer data

Integer data is stored in memory in the form of complement code. The reason is: using the complement code, the sign bit and the value field can be processed uniformly; at the same time, addition and subtraction can also be processed uniformly (the CPU only has an adder). In addition, the operation process of the complement code and the original code is the same. Additional hardware circuitry is required.

 From the above figure, we know that all the complements are stored in the memory, but why is it in the order from the back to the front? It is because there is a form of big and small endian storage. The next step is to introduce big and small endian storage.

2.3 Big and small endian introduction

2.3.1 What is big endian and little endian

Big-endian (storage) mode means that the low bits of data are stored in the high addresses of the memory, while the high bits of data are stored in the low addresses of the memory
;
the
little-endian (storage) mode means that the low bits of data are stored in the low address, while the high-order bits of the data are stored in the high
address of the memory.

In this picture, the typical low bits are stored in the low address of the memory, and the high bits of the data are stored in the high address of the memory (little endian storage mode).

2.3.2 Why there is a big and small endian mode

Why is there a difference between big and small endian modes? This is because in the computer system, we use bytes as the unit, and each address unit
corresponds to a byte, and a byte is 8 bits. But in the C language, in addition to the 8-bit char, there are also 16-bit short
types and 32-bit long types (depending on the specific compiler). In addition, for processors with more than 8 bits, such as 16-bit Or a 32-
bit processor, since the register width is greater than one byte, there must be a problem of how to arrange multiple bytes. Therefore
, it leads to big-endian storage mode and little-endian storage mode.
For example: a 16bit short type x, the address in the memory is 0x0010, the value of x is 0x1122, then 0x11 is the
high byte, and 0x22 is the low byte. For big-endian mode, put 0x11 in the low address, that is, 0x0010, and put 0x22 in the high
address, that is, 0x0011. Little endian mode, just the opposite. Our commonly used X86 structure is little-endian mode, while KEIL C51
is big-endian mode. Many ARMs and DSPs are in little-endian mode.
Some ARM processors can also choose the big-endian mode or the little-endian mode by hardware .

2.3.3 The respective advantages of big and small endian storage

Advantages of little endian mode :

  • The low address of the memory stores the low byte, so there is no need to adjust the content of the byte when converting the data (Note: For example, when converting 4 bytes of int to 2 bytes of short, the int data is stored directly Just give the first two bytes to short, because the first two bytes are just the lowest two bytes, which conforms to the conversion logic);
  • When the CPU does numerical calculations, it fetches data from the memory in order from low to high for calculation until the highest sign bit is refreshed at the end. This operation method will be more efficient.

Advantages of big endian mode :

  • The sign bit is in the first byte of the memory of the represented data, which is convenient for quickly judging the positive and negative and the size of the data
  • Their respective advantages are the disadvantages of each other. Because the two are equal to each other, coupled with the insistence of some hardware manufacturers, there is never a unified standard for multi-byte storage order.

3. Storage of floating point numbers in memory

3.1 Examples of floating-point storage

int main()
{
    int n = 9;
    float *pFloat = (float *)&n;
    printf("n的值为:%d\n",n);
    printf("*pFloat的值为:%f\n",*pFloat);

    *pFloat = 9.0;
    printf("num的值为:%d\n",n);
    printf("*pFloat的值为:%f\n",*pFloat);
    return 0;
}

And the result of running this code is:

 

 But why is there such a big gap between the results of the interpretation of integers and floating-point numbers of the same number, then we need to understand the storage rules of floating-point numbers.

3.2 Rules for storage of floating point numbers

3.2.1 Binary representation and decimal conversion of floating point numbers

 3.2.2 IEEE 754 regulations

According to the international standard IEEE (Institute of Electrical and Electronics Engineering) 754, any binary floating-point number V can be expressed in the following form:

  • (-1)^S * M * 2^E
  • (-1)^S represents the sign bit, when S=0, V is a positive number; when S=1, V is a negative number.
  • M represents a valid number, greater than or equal to 1 and less than 2.
  • 2^E means exponent bits.
     

 for example:

  • 5.0 in decimal is 101.0 in binary, which is equivalent to 1.01×2^2.
  • Then, according to the format of V above, it can be concluded that S=0, M=1.01, and E=2.
  • Decimal -5.0, written in binary is -101.0, which is equivalent to -1.01×2^2. Then, S=1, M=1.01, E=2.

Floating point number storage model: 

 (1) For 32-bit floating-point numbers, the highest 1 bit is the sign bit s, the next 8 bits are the exponent E, and the remaining 23 bits are the effective number M.

 (2) For 64-bit floating-point numbers, the highest bit is the sign bit S, the next 11 bits are the exponent E, and the remaining 52 bits are the effective number M.

3.2.3 IEEE 754’s special regulations on significant digits M and exponent E:

1. Special regulations for effective number M:

As mentioned earlier, 1≤M<2, that is to say, M can be written in the form of 1.xxxxxx, where xxxxxx represents the decimal part.
IEEE 754 stipulates that when M is saved inside the computer, the first digit of this number is always 1 by default, so it can be discarded, and only the following xxxxxx part is saved. For example, when saving 1.01, only save 01, and then add the first 1 when reading. The purpose of doing this is to save 1 significant figure. Taking the 32-bit floating-point number as an example, there are only 23 bits left for M. After the first 1 is discarded, it is equivalent to saving 24 significant figures.

2. Special provisions for Index E:

1.1 Regulations on intermediate numbers (in order to distinguish positive and negative exponents)

First, E is an unsigned integer (unsigned int), which means that if E is 8 bits, its value range is 0~255; if E is 11 bits, its value range is 0~2047. However, we know that E in scientific notation can have negative numbers, so IEEE 754 stipulates that an intermediate number must be added to the real value of E when stored in memory. For 8-bit E, this intermediate number is 127 ; For 11-bit E, this intermediate number is 1023 . For example, the E of 2^10 is 10, so when saving it as a 32-bit floating point number, it must be saved as 10+127=137, which is 10001001

1.2 E is not all 0 or not all 1

At this time, the floating-point number is represented by the following rules, that is, the calculated value of the exponent E is subtracted by 127 (or 1023) to obtain the real value, and then the
first digit 1 is added before the effective number M.
For example:
The binary form of 0.5 (1/2) is 0.1. Since the positive part must be 1, that is, the decimal point is shifted to the right by 1 bit, then it is
1.0*2^(-1), and its order code is -1+127= 126, expressed as 01111110, and the mantissa 1.0 removes the integer part to be 0, and fills 0 to 23 digits 000000000000000000000000, then its binary representation is:

0 01111110 00000000000000000000000

1.3 E is all 0

At this time, the exponent E of the floating-point number equal to 1-127 (or 1-1023) is the real value, and the effective number M is no longer added with the first digit of 1, but is restored to a decimal of 0.xxxxxx. This is done to represent ±0, and very small numbers close to 0.

1.4 E is all 1

At this time, if the significant number M is all 0, it means ± infinity (positive or negative depends on the sign bit s);
 

Finally: Code text is not easy, ask for one-click three links.

Guess you like

Origin blog.csdn.net/qq_64293926/article/details/127351107