c language-storage of data in memory


1. Storage of integers in memory

1. There are three binary representation methods of integers, namely original code, complement code and complement code
2. The three representation methods all have two parts: sign bit and numerical bit. , the sign bit uses 0 to represent "positive" and 1 to represent "negative". The highest bit of the numerical bit is used as the sign bit, and the rest are numerical bits.
3. When storing, the complement code is stored, and when taken out, the original code is taken out

For example:
Insert image description here
Original code, complement code and complement code conversion of positive and negative numbers

The original, inverse and complement codes of positive integers are the same.
There are three different ways of representing negative integers. Original code: The original code is obtained by directly translating the value into binary in the form of positive and negative numbers. Complement code: Keep the sign bit of the original code unchanged, and invert the other bits bit by bit to get the complement code. Complement code: the complement code + 1 is the complement code.
To convert the original code into the complement code, just reverse the above process: the complement code -1 gets the complement code, the sign bit of the complement code remains unchanged, and the other bits are inverted bit by bit to get the original code.

For example, storing int type -1, and 1
Insert image description here

For shaping: the data stored in the memory actually stores the complement code.

Why?
In computer systems, values ​​are always represented and stored using one's complement codes.
The reason is that using the complement code, the sign bit and the numerical 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 complement code is different from the original code. The operation process for mutual conversion is the same and no additional hardware circuit is required.

Unsigned type:
The sign bit is removed and all bits are regarded as numerical bits
Insert image description here
The original code, complement code and complement code of the unsigned bit Same
such as: unsigned int 1, -1
![Insert image description here](https://img-blog.csdnimg.cn/direct/c2af36d05c584bf8a32a5ccef41f35ea.png

2. Big and small endian byte order and byte order judgment

What is big and small endianness?

In fact, when more than one byte of data is stored in memory, there is a problem of storage order. According to different storage orders, we divide
into big-endian byte order. Storage and little-endian byte order storage, the following are the specific concepts:
Big-endian (storage) mode: means that the low-order byte content of the data is stored at the high address of the memory, and the data The high-order byte content is stored at the low address of the memory.
Little endian (storage) mode: means that the low-order byte content of the data is stored at the low address of the memory, and the high-order byte content of the data is stored at the high address of the memory.

Why is there big and small endianness?

This is because in the computer system, we use bytes as the unit, each address unit corresponds to a byte, and a byte is 8 bits, but in C language except In addition to 8-bit > char, there are also 16-bit short type and 32-bit long type (depending on the specific compiler). In addition, for processors with more than 8 bits, such as 16-bit or 32-bit For processors, since the register width is greater than one byte, there must be a problem of how to arrange multiple bytes. This leads to big-endian storage mode and little-endian storage mode.
For example: a 16-bit short type x, the address in the memory is 0x0010, and 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 0x22 in the high address, that is, 0x0011. Little endian mode is just the opposite. Our commonly used X86 structure is little endian mode, while KEIL C51 is big endian mode. Many ARM and DSP are in little-endian mode. Some ARM processors can also select big-endian or little-endian mode by hardware.

Example:
How to store 0x11223344

int main() {
    
    
	int a = 0x11223344;
	return 0;
}

Insert image description here
Exercise:
Design a small program to determine the byte order of the current machine

1. The difference between big endian and little endian lies in the byte order of storage
2. We only need to take one byte of the lower address to see whether it is big endian or little endian.

Code:

#include <stdio.h>
int check_sys()
{
    
    
 int i = 1;//设置i=1,只观察第一个字节
 return (*(char *)&i);//强制类型将&i转为char*(为了只取第一个字节),再解引用得到第一个字节的内容
}
int main()
{
    
    
 int ret = check_sys();//调用函数,看返回值
 if(ret == 1)
 {
    
    
 printf("⼩端\n");
 }
 else
 {
    
    
 printf("⼤端\n");
 }
 return 0;
 }

3. Storage of floating point numbers in memory

**1. Common floating point numbers: **3.14159, 1E10, etc. The floating point number family includes: float, double, long double types.
The range of floating point number representation: defined in float.h

2. Storage of floating point numbers
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: < /span> • 2^E represents the exponent • M represents a significant figure, M is greater than or equal to 1 and less than 2 • (−1)S represents the sign bit. When S=0, V is a positive number; when S= 1, V is a negative number
V = (−1) ∗ S M ∗ 2E




Insert image description here

IEEE 754 stipulates:

For a 32-bit floating point number, the highest 1 bit stores the sign bit S, the next 8 bits store the exponent E, and the remaining 23 bits store the significant number M
For 64 bits A floating point number, the highest 1 bit stores the sign bit S, the next 11 bits store the exponent E, and the remaining 52 bits store the significant number M

Float type floating point number memory allocation
Insert image description here

Double type floating point number memory allocation
Insert image description here

3. The process of storing floating point numbers
IEEE 754 has some special provisions for the significant digit M and the exponent E.

As mentioned before, 1≤M<2, that is to say, M can be written in the form of 1.xxxxxx, where xxxxxx represents the number part. IEEE 754
stipulates that when M is stored 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 01 is saved, and when reading, the first 1 is added. The purpose of this is to save 1 significant figure. Taking a 32-bit floating point number as an example, there are only 23 bits left for M. After the 1 in the first bit is rounded off, 24 significant digits can be saved.

As for the index E, the situation is more complicated.

First of all, E is an unsigned int (unsigned int)
This 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 be a negative number, so IEEE
754 stipulates that an intermediate number must be added to the real value of E when stored in memory. For 8 For an E of 11 digits, the intermediate number is 127; for an E of 11 digits, the intermediate number is 1023. For example, the E of 2^10 is 10, so when it is saved as a 32-bit floating point number, it must be saved as 10+127=137, which is 10001001.

We store the above example:
Assume that 5.5 is a float type
Insert image description here
The first bit of M can be omitted, and the number after the decimal point can be stored< /span>
4. The process of obtaining floating point numbers

S ->Judge positive or negative
M-> Take out in the order of storage, and add 1 in front, as in the above example: .011, and then add 1 in front 1->M=1.011
The index E taken out from the memory can be further divided into three situations:
E is not all 0 or not all 1 00000000000000000000000, then its binary representation is: 0 01111110 00000000000000000000000
At this time, the floating point number is represented by the following rules, that is, the calculated value of the exponent E is subtracted from 127 (or 1023) to obtain the real value, and then the first digit of 1 is added before the significant digit. For example: the binary form of 0.5 is 0.1. Since the positive part must be 1, that is, if the decimal point is moved to the right by 1 place, it is 1.0*2^(-1), and its exponent code is -1+127 (intermediate value) =126, expressed as 01111110, and the mantissa 1.0 removes the integer part to 0, and fills in 0 to 23 digits At this time, the exponent E of the floating point number is equal to 1-127 (or 1-1023), which is the real value, and the effective digit M does not add the first digit. of 1, but restored to a decimal of 0.xxxxxx. This is done to represent ±0, and very small numbers close to 0. For example: 0 0000000000100000000000000000000 E is all 1 At this time, if the valid digits M are all 0, it means ± infinity (the sign bit depends on the sign bit) s) Such as: 0 11111111 00010000000000000000000




5. Precision problem
When storing a floating point number, the number of stored bits is limited, fioat-23 bits, double-52 bits. Once this number is exceeded, There will be a problem of loss of accuracy
For example: when printing 99.7

int main() {
    
    
	float a = 99.7;
	printf("%f", a);
	return 0;
}

Run result:
Insert image description here
Some data was lost.
Summary:

(1) Some floating point numbers cannot be accurately saved in memory
(2) The precision of double must be higher than that of float
(3) Floating point number Problems may arise when comparing

practise:

#include <stdio.h>
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;}

What is the output?
Insert image description here

Analysis:
Insert image description here

The above is what I shared. If there are any mistakes, please leave a message in the comment area.
Finally, thank you everyone for watching!

Guess you like

Origin blog.csdn.net/2302_79539362/article/details/134684800