[C language] Detailed explanation of data storage in memory

1. What is a data type

We can think of the data type as a rectangular box. Types such as int and char are different boxes that can store things (data) of different sizes (that is, the size of the storage space). The meaning of the type: use this type to open
up
memory The size of the space (the size determines the scope of use)
how to look at the perspective of the memory space.

Two, the basic classification of types

insert image description here
Notice:
The character is stored in the memory as the ASCII code value of the character, and the ASCII code value is an integer, so the character is classified into the integer family.
Whether char is signed char or not is not stipulated by the C language standard, it depends on the compiler.

3. Storage of integers in memory

The creation of a variable is to open up space in memory. The size of the space is determined according to different types.
Next, let's take a look at how the data is stored in the space opened up in memory.

1. Original code, inverse code, complement code

First of all, we need to know that there are three representation methods for integers in computers : original code , inverse code, and complement code . part.

  • The original, inverse and complement of positive integers are the same
  • The three representations of negative integers are different
    • The original code can directly translate binary into binary in the form of positive and negative numbers
    • The inverse code keeps the sign bit of the original code unchanged, and the other bits can be obtained by inverting the other bits in turn.
    • Complement code inverse + 1 to get complement code
      Noticefor integersThe data stored in the memory is actually stored in complement code
      The reason is that in computer systems, values ​​are always represented and stored in complement code. The reason is that, using complement code, the sign bit and the value field can be processed uniformly. At the same time, addition and subtraction can also be processed in a unified way (the CPU only has an adder). In addition, the complement code and the original code are converted to each other, and the operation process is the same, and no additional hardware circuit is required.

2. Big and small endian

(1) What is big and small endian

premise:
insert image description here

Endian byte order refers to the byte order in which data is stored on the computer

  • Big-endian (storage) mode, which means that the low bits of data are stored in the high address of the memory , and the high bits of the data are stored in the low address of the memory
    insert image description here

  • Little endian (storage) mode, which means that the low bits of the data are stored in the low addresses in the memory, and the high bits of the data are stored in the high addresses of the memoryMemorize( low low high high )
    insert image description here
    Among them, in VS2022, it is the little endian mode used
    insert image description here

(2) Why are there big and small ends

Because in the computer system, 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.
[Example] A 16bit 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 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 KEILC51 is big-endian mode. Many ARMDSPs are little-endian. Some ARM processors can also choose the big-endian mode or the little-endian mode by the hardware
[system engineer written test questions]

Please briefly describe the concepts of big-endian and little-endian, and design a small program to determine the byte order of the current machine.

insert image description here

#include<stdio.h>
int check_sys() 
{
    
    
	int a = 1;
	char* p = (char*) & a;//拿到一个字节地址

	if (*p == 1)
		return 1;
	else
		return 0;

	//可以有优化 return *( (char*)&a ); 
}
int main() 
{
    
    
	if (check_sys())
		printf("小端\n");
	else
		printf("大端\n");

	return 0;
}

4. Storage of floating-point types in memory

Common floating point numbers:

  • 3.141592
  • 1E10 This E is equivalent to exponential scientific notation 1 * 10^10 1 times 10 to the 10th power.
    Floating-point number family includes: float, double, long double types.
    The range of floating-point numbers (detailed below): (In vs, #include<float.h> Go to the definition to view) It does n’t matter if the following pictures are difficult to understand
    insert image description here

1. Floating-point number storage rules

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 bit

[Example] Decimal system: 9.0 is written as binary 1001.0 and rewritten as 1.001* 2^3 to (-1) ^0 * 1.001 * 2 ^ 3. S = 0, M = 1.001, E = 3.
The IEEE standard provides two main formats for floating-point numbers: single-precision (32-bit) and double-precision (64-bit) . Divided into three sections: sign, exponent, and decimal . The exponent part determines the range of the floating point number. The number of digits in the fractional part determines the precision. (See below)

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 significand M.
For a 64-bit floating-point number, the highest bit is the sign bit S, the next 11 bits are the exponent E, and the remaining 52 bits are the significand M.
insert image description here
NoticeIEEE754 has other regulations on the significant number M and exponent E

1≤M<2, that is, M can be written in the form of 1.xxxxxx, where xxxxxx represents the fractional part.
Significant number M
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 xxxxxx part that follows 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.
Exponent E
E is an unsigned integer, if E is 8 bits (0~255), E is 11 bits (0~2047). And because E in the scientific notation method can have negative numbers, IEEE 754 stipulates that an intermediate number must be added to the real value of E when stored in the memory. For 8-digit E, the intermediate number is 127; for 11-digit E, the middle 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, that is, 10001001.
next discussion

  • When E is all 1 , when M is all 0, it means infinity (positive or negative depends on the sign bit S)
  • When E is all 0 , the effective number M will no longer add the first 1, but will be reduced to a decimal of 0.xxxxxx. This is done to represent ±0, and
    very small numbers close to 0.
  • When E is not all 0 and 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 is added before the effective number M 1. The binary form of 0.5 (1/2) is 0.1. Since the positive part must be 1, that is, the decimal point is moved to the right by 1 bit, 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, fills 0 to 23 digits 00000000000000000000000, then its binary representation is: 0 01111110 00000000000000000000000

5. Practice

What does the following code output?

1.

#include<stdio.h>
int main() 
{
    
    
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d,b=%d,c=%d\n",a,b,c);
	return 0;
}

[Result] a=-1, b=-1, c=255
analyze
insert image description here

2.

#include<stdio.h>

int main() 
{
    
    
	char a = -128;
	printf("%u\n",a);
	return 0;
}

【Result】4294967168
analyze
insert image description here

3.

#include<stdio.h>

int main() 
{
    
    
	char a = 128;
	printf("%u\n",a);
	return 0;
}

【Result】4294967168
analyze
insert image description here

4.

#include<stdio.h>

int main() 
{
    
    
	int i = -20;
	unsigned int j = 10;
	printf("%d\n",i+j);
	return 0;
}

【Result】-10
analyze
Operate in the form of two's complement, and finally format it into a signed integer
insert image description here

5.

#include<stdio.h>
int main() 
{
    
    
	unsigned int i;
	for (i = 9; i >= 0;i--)
	{
    
    
		printf("%u\n",i);
	}
	return 0;
}

[Result] Infinite loop
analyze
unsigned int (range 0~4294967295) can never be less than 0
The judgment condition of the for loop is i >= 0

6.

int main() 
{
    
    
	char a[1000];
	int i;
	for (i = 0; i < 1000;i++)
	{
    
    
		a[i] = -1 - i;
	}
	printf("%d",strlen(a));
	return 0;
}

【Result】255
analyze
insert image description here

7.

#include<stdio.h>
unsigned char i = 0;
int main() 
{
    
    
	for (i = 0; i <= 255;i++)
	{
    
    
		printf("hello world\n");
	}
	return 0;
}

[Result] Infinite loop print hello world
analyze
The range of unsigned char is 0~255, so the value range of i cannot be greater than 255, and the judgment part of the for loop will not stop

Guess you like

Origin blog.csdn.net/qq_72505850/article/details/132129359