当前位置:网站首页>C language: data storage in memory

C language: data storage in memory

2022-06-13 09:11:00 Caixinzhi

This data storage in memory will be divided into two parts : One is the storage of integer in memory ; The second is the storage of floating-point type in memory .

One 、 The storage of integers in memory . First , We need to know the original code 、 Inverse code 、 Complement code , These three have been sorted out in detail before , I'll just tell you more about it . Next, let's take a look at the size side ( Big endian byte order & Small endian byte order ).

that , What are the big and small ends ?

Storage mode of large end byte order : There is a high address in the low order , There is a low address in the high order .

Storage mode of small end byte order : There is a low address in the low order , High address exists in high bit .

( among , The smallest unit of size is byte !)

Next , It will describe how to use a program to determine whether the machine used is a big end or a small end .

#include <stdio.h>

int check_sys()
{
	int a = 1;
	char* p = (char*)&a;
	if (*p == 1)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int main()
{
	int ret = check_sys();   // return 1 It's the small end , return 0 It's the big end 
	if (ret == 1)
	{
		printf(" The small end \n");
	}
	else
	{
		printf(" Big end \n");
	}
	return 0;
}

The main idea of this code is :check_sys Function by casting , Extract whether the data stored in a byte size is equal to the first byte data in memory , If equal , Is the small end byte order ; If not , Is the big endian byte order .

Because the value we take 1 Is a very special value , therefore , We can also simplify the code further , See below for the specific code :

#include <stdio.h>

int check_sys()
{
	int a = 1;
	return *(char*)&a;
}

int main()
{
	int ret = check_sys();   // return 1 It's the small end , return 0 It's the big end 
	if (ret == 1)
	{
		printf(" The small end \n");
	}
	else
	{
		printf(" Big end \n");
	}
	return 0;
}

After understanding the original code 、 Inverse code 、 After the complement and the contents of the size side , We can study signed and unsigned integers , It will be explained through the following topics :

Topic 1 :

// What the following code will output ?
#include <stdio.h>
int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d, b=%d, c=%d", a, b, c);
	return 0;
}

about a In terms of variables , here -1 yes int type , Turn into char Type truncation occurs , Because the binary complement is stored in memory , therefore , Truncation also truncates the binary complement in memory , Only the lowest 8 Bits of data , And because in the end %d Printed out in the form of , Therefore, the retained data will be promoted by integer , For signed integer lifts , Will fill the sign bit in the highest bit of the binary , Finally, it is converted to the original code by complement , You will find , Finally print it out a The value of is -1.

about b In terms of variables , although C There is no provision in the language char And signed char It's the same , But in many mainstream compilers , Will default to char Namely signed char, For example, I often use VS2019 etc. , therefore , Last b The printed results will also a equally , by 1.

about c In terms of variables , Preceded by a sign char equally , But when it comes to integer lifting , For unsigned integer lifts , Will fill in the highest bit of binary 0, Finally print it out c The value is 255.

Topic two :

// What the following code will output ?
#include <stdio.h>
int main()
{
	char a = -128;
	printf("%u\n", a);
	return 0;
}

First ,-128 When stored in memory as a complement , stay char Truncation occurs in types , because char Stored is a signed type , Therefore, integer promotion occurs during printing , Will fill the sign bit in the highest bit of the binary , And then because it uses %u Printed , Therefore, it will be automatically recognized as an unsigned number in memory , So the original code will be equal to its complement , The number of prints will be very large .

Topic three :

// What the following code will output ?
#include <stdio.h>
int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}

This question is similar to question two , Just put -128 Change it to 128, And then you'll find out ,128 The binary sequence put in after truncation is the same as -128 The truncated binary sequences are equal , So after the same calculation , It will print out a very large amount of data just like topic 2 .

Topic four :

// What the following code will output ?
#include <stdio.h>
int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	return 0;
}

This is a relatively simple question , Used to distinguish the previous questions , Directly use two binary data stored in memory to calculate , Get the binary and then print out the original code , You will see that the result is -10.

Topic 5 :

// What the following code will output ?
#include <stdio.h>
int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	return 0;
}

because i It's an unsigned integer , And when printing, it is printed with %u In the form of printing , So when i Reduced to 0 When , At the beginning of the next cycle ,i by -1, Its binary complement 32 Bits become all 1, In the case of unsigned , The original code is equal to the complement , By this time i Will become a very large value , Then this very large value will continue to decrease to 0, Then it becomes very big , This infinite cycle goes on .

Topic 6 :

// What the following code will output ?
#include <stdio.h>
int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}

This is an important question , because char At most 8 A bit , When char When it is unsigned , Its value range is from 0 To 255; And in the sign char in , The value range is from -128 To 127, however , Whether signed or unsigned , Their length (strlen) It's all the same , by 255. therefore , The final printed result is 255.

inference : Different integer types have a certain value range , And there are different value ranges for whether there is a symbol or not . You can use the header file for details limits.h Go to the document to view .

Topic 7 :

// What the following code will output ?
#include <stdio.h>

unsigned char i = 0;

int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}

This problem is similar to the previous one , Because there is no sign char The range of theta is zero 0 To 255, therefore i The value of cannot be greater than 255 Of ,for The condition in the loop is always true , So the program prints in an infinite loop .

Two 、 Storage of floating point in memory . This part will lead to... Through an example .

Example :

#include <stdio.h>
int main()
{
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n The value of is :%d\n", n);   //9
	printf("*pFloat The value of is :%f\n", *pFloat);   //0.000000
	*pFloat = 9.0;
	printf("n The value of is :%d\n", n);   //1091567616
	printf("*pFloat The value of is :%f\n", *pFloat);   //9.000000
	return 0;
}

Before looking at this code , We need to know that the rules for storing floating-point numbers and integers in memory are different , You can't use the integer method directly , that , What are the storage rules for floating point numbers ?

For any binary floating-point number V Can be expressed in the following form :(-1)^S*M*2^E

1.(-1)^S The sign bit , When S=0,V Is a positive number ; When S=1,V It's a negative number .

2.M Represents a significant number , Greater than or equal to 1

3.2^E Indicates the index bit

for example :5.5 Convert to binary to 101.1( That is to say -1^0*1.011*2^2)

Through the description above , It can be inferred that , Binary floating-point numbers only need to be stored in memory S、M、E Just three values , How are these three numbers stored in memory ?

For single precision floating point numbers float( That is to say 32 Bit floating point ) For storage , The highest bit is the sign bit S, next 8 Bits are exponents E, The rest 23 Bits are significant numbers M.

For double precision floating point numbers double( That is to say 64 Bit floating point ) For storage , The highest bit is the sign bit S, And then 11 Bits are exponents E, The rest 52 Bits are significant numbers M.

M Deposit of : Because significant numbers M The range of values is always greater than or equal to 1 Less than 2 Of , So the positive part will be stored 1 Give up , Save only the decimal part in memory .

E Deposit of :E Is an unsigned number , If it's negative , In memory E The true value of must be added with an intermediate number , about 8 Bit E, The median number is 127; about 11 Bit E, The median number is 1023.

You know how floating-point numbers are stored , Next , It is necessary to understand how it is taken out .

Three cases of fetching from memory :

1.E Not all for 0 Or not all of them 1: Index E The calculated value of minus 127( or 1023), Get the real value ; And then the significant number M Add first place before 1 that will do .

2.E All for 0: Index E be equal to 1-127( or 1-1023) That's the true value ; Significant figures M Directly for 0.XXX, In this way, it is easy to see that it is an infinite close to 0 Number of numbers .

3.E All for 1: And E All for 0 contrary , Is a number close to infinity .

Through the above series of rules , We can make the above example well , The above example has four prints , Next , Just list the four prints one by one .

First print : Because it is an integer 、 Integer extraction , So the result must be printed out 9.

Second print : Because it is a floating-point number , So it will be stored in the original memory 32 Bits to restore , It will find E For all 0. It is not difficult to see from the second of the three cases taken from the memory above , The restored floating-point number is an infinitely close to 0 Number of numbers .

The third print : According to the conversion rules of floating point numbers ,9.0 Convert to binary to 1001.0( That is to say -1^0*1.001*2^3), And then because you want to take it out in the form of an integer , So write this by floating point numbers 32 A bit , Turn to the original code , Read it as an integer , You can get 1091567616 The result is .

The fourth print : Because it is a floating-point number that is stored in 、 Floating point number extraction , So the result must be printed out 9.000000.

原网站

版权声明
本文为[Caixinzhi]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202270533005360.html