[C language] data storage in memory


1. Data type introduction

char character data type
short short integer
int integer
long long integer
long long longer integer
float single precision floating point
double double precision floating point

1. Basic classification of data types

integer family

char
unsigned char
signed char

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

floating point family

float
double

construction type

Array type
Structure type struct
enumeration type enum
joint type union

pointer type

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

empty type

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


Second, the storage of integers in memory

1. Original code, inverse code, complement code

There are three binary representation methods for integers in computers, namely, original code, inverse code, and complement code.
The three representation methods have two parts, the sign bit and the value bit . The sign bit uses 0 to represent "positive", 1 to represent "negative", and the value bit
正数的原、反、补码都相同。
There are three different ways of representing negative integers.

Original code
The original code can be obtained by directly translating the value into binary in the form of positive and negative numbers.

Inverse code
Keep the sign bit of the original code unchanged, and invert the other bits in turn to get the inverse code

Complement code
Inverse code + 1 to get complement code

***对于整形来说:数据存放内存中其实存放的是补码。***

In computer systems, values ​​are always expressed and stored in two's complement. The reason is that, 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, and no additional hardware circuits are required.
And the value 0 can only be expressed in one's complement code, and has two representations in original code and inverse code.

2. Big and small endian introduction

Let's look at the storage of integers in memory:

insert image description here
Both a and b are stored in two's complement, but don't we find that the order of storage is a bit strange?

2.1 Definition of big and small endian

Big-endian (storage) mode: It means that the low bits of the data are stored in the high addresses of the memory, and the high bits of the data are stored in the low addresses of the memory.
Little endian (storage) mode: It means that the low bits of the data are stored in the low addresses of the memory, while the high bits of the data are stored in the high addresses of the memory.

Let me give you an example.
For example, in the above screenshot, the value stored in variable a is 00 00 00 14 (hexadecimal), we will find that 14 is stored in the low address of the memory as the low bit of data , and 00 is stored in the high address as the high bit , so it is obvious that the storage mode of the compiler is little-endian storage.

2.2 Significance of big and small endian

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 32-bit processors, 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

2.3 How to know the storage mode of the compiler?

int check_sys()
{
    
    
	int i = 1;
	//1的16进制表示是00 00 00 01
	//如果是小端存储,取出的就是01,则返回1
	//反之如果是大端存储取出的就是0,返回0
	return (*(char*)&i);
}
int main()
{
    
    
	int ret = check_sys();
	if (ret == 1)
	{
    
    
		printf("小端\n");
	}
	else
	{
    
    
		printf("大端\n");
	}
	return 0;
}

3. Floating-point storage in memory

1. Floating-point number storage rules

举个例子
5.5如何用二进制表示?5.5分成两部分50.55的二进制表示是101,即1*2^2 + 0*2^1 + 1*2^0
我们知道小数点左边第一位表示2^0,第二位表示2^1,依次类推,那么小数点右边呢,
其实是从2^-1开始依次-12^-2这样,所以0.5就是1*2^-1,这样5.5就是101.1
然后将101.1用科学计数法表示就是 1.011*2^2.

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.

那么5.5用这个标准表示就是 (-1)^0 * 1.011 * 2^2,在这个式子中S就是0,M就是1.011,E就是2

IEEE 754 states:
For a 32-bit floating-point number, the highest 1 bit is the sign bit s, the next 8 bits are the exponent E, and the remaining 23 bits are the significand
insert image description here
M.
insert image description here

1.1 S storage

Very simple, store 0 for positive numbers and 1 for negative numbers

1.2 M storage

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, 24 significant figures can be saved.

1.3 Exabytes of storage

First, the standard states that E is an unsigned integer.
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.
But we know that in scientific notation, E can be a negative number. For example, the scientific notation of 0.5 means (-1) ^ 0 * 1.0 * 2 ^ (-1). Therefore, IEEE 754 stipulates that an intermediate number must be added to the real value of E when stored in memory. For 8-digit E, the
intermediate number is
127; For 11-bit E, this intermediate number is1023.
In this way, the E of 0.5 is -1+127=126 when stored, and the binary value is 0111 1110. Here it has nothing to do with the original inverse complement code, it is the binary representation of 126, which is the original code.

所以0.5在内存中的存储形式即为:
前面的0是符号位,中间就是126的二进制表示形式,最后就是1.0去表整数1,剩下0,然后补齐0230 01111110 00000000000000000000000

1.4 The index E is fetched from the memory

1.4.1 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.

1.4.2 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.
Significant number M no longer adds the first 1, but restores to a decimal of 0.xxxxxx. This is done to represent ±0, and
very small numbers close to 0.

1.4.3 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);


Summarize

The above is what I want to talk about today. This article briefly introduces how various types of values ​​are stored in memory. I believe it can help you understand the logic of C language more deeply.

Guess you like

Origin blog.csdn.net/lyq2632750277/article/details/126254597