Data storage analysis and examples

1. Original code, one's complement, and one's complement
For unsigned numbers, the original one's complement is the same. The three representation methods of the
original one's complement and one's complement
have two parts: the sign bit and the value bit. The sign bit is all expressed by 0. "Positive", use 1 to represent "negative", and the three representation methods of the value bit are different.
①Original code
Directly translate the binary into binary in the form of positive and negative numbers.
②The inverse code
//The sign bit of the original code remains unchanged , The other bits can be obtained by
inverting them in turn. ③'s complement
//add 1 to the inverted code

int main()
{
    
    
	int a = 20;
	//00000000000000000000000000010100  --原码
	//00000000000000000000000000010100  --反码
	//00000000000000000000000000010100  --补码
	//转化为16进制位
	//0x00000014    在VS的编译器中他的存储方式是小端字节序
	int b = -10;
	//1000000000000000000000001010 -- 原码
	//1111111111111111111111110101 -- 反码
	//1111111111111111111111110110 --补码
	//0xFFFFFFF6 
}

Insert picture description here

For plastic shaping: the data is actually stored in the memory as complements.
Why?
1. In the computer system, the value is always expressed and stored in complement. The reason is that with the complement code, the sign bit and the value field can be processed at the same time; at the same time, addition and subtraction can also be processed at the same time, and there is only an adder in the CPU
. Then you will say whether 1-1 can’t be calculated. Up?
Convert to 1+ (-1)

2.
Big-endian introduction Big-endian storage mode: refers to the low-order data stored in the high address of the memory, while the high-order data is stored in the low address of the memory;
little-endian storage mode: refers to the low-order data stored in the memory In the low address, the high
bit of the data is stored in the high address of the memory; for the VS compiler, it is the little-endian storage mode, and the left side is the low address, and the right side is the high address. Low--------- -------High
Question: Design a small program to judge the endianness of the current machine.
Analysis: We take out the first byte of an integer, such as int a = 1 0x00000001
big endian mode 00 00 00 01
Little-endian mode 01 00 00 00
If 00 means big-endian, 01 means little-endian,
here encapsulate a function to determine the current machine's big-endian

int check_sys()
{
    
    
	int a = 1;
	char* p = (char*)&a;
	//返回1表示小端
	//返回0表示大端
	return *p;
}
int main()
{
    
    
	int a = 1;
	char* p = (char*)&a; //char* 能表示我当前访问的自己大小
	int ret = check_sys();
	if (ret == 1)
	{
    
    
		printf("小端\n");
	}
	else
	{
    
    
		printf("大端\n");
	}
	return 0;
}

Question 2.
What to output?

int main()
{
    
    
	//10000000000000000000000000000001
	//11111111111111111111111111111110
	//11111111111111111111111111111111
	char a = -1;
	//11111111
	//应为打印的是%d所以这里要发生整形提升,对于char来说是有符号的
	//所以前面补符号位
	//11111111111111111111111111111111 -- 补码
	//原码就是-1
	signed char b = -1;
	//11111111
	//和char的性质一样
	unsigned char c = -1;
	//11111111  最前面的并不是符号位,所以发生整形提升的时候补充0
	//0000000000000000000110011111111
	//所以对应的十进制数就是255
	printf("a = %d,b = %d,c = %d", a, b, c);
	return 0;
}
//结果是 -1 -1 255

Question 3.
What is the output?


int main()
{
    
    
	char a = -128;
	//10000000000000000000000010000000 
	//11111111111111111111111101111111
	//11111111111111111111111110000000
	//发生截断
	//10000000
	//11111111111111111111111110000000--补码
	//但是对于一个无符号数来说,原反补是相同的
	//所以a = 4294967168转换为无符号十进制数  是一个很大的数字
	printf("%u\n", a);  //%u--打印十进制的无符号数
	return 0;
}

The range of a char is
0-127 -1 — -128 This can be expressed as the left part of a disc is -1 from top to bottom —> -128 The right side is 127 from bottom to top --> 0 The
overall range is -128 --> 127
Insert picture description here

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

//这里你要思考对于一个char类型能存储下一个128吗?
int main()
{
    
    
	char a = 128;  //127 + 1  根据上面的圆盘就知道其实也是打印出来-128的意思
	printf("%u\n", a);
	return 0;
}

Operate in the form of one's complement, and finally format into a signed integer

int main()
{
    
    
	int i = -20;
	unsigned int j = 10;
	//10000000 00000000 00000000 00010100
	//11111111 11111111 11111111 11101011
	//11111111 11111111 11111111 11101100 -- -20补码
	//00000000 00000000 00000000 00001010 -- 10的补码
    //11111111 11111111 11111111 11110110  --结果
	//11111111 11111111 11111111 11110101 -- 结果的补码
	//10000000 00000000 00000000 00001010  -- 结果原码  -10
	printf("%d\n", i + j);
}

what's the result?

#include<windows.h>
int main()
{
    
    
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
    
    
		printf("%u\n", i);
		Sleep(100);// 单位是ms  也就是0.1s 
	}
	return 0;
}
//你会发现对于一个unsigned int 类型的压根就不可能小于0,所以这是一个死循环

Classic question

int main()
{
    
    
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
    
    
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}
//结果 255   因为对于char 来说-128 --> 127 的范围,你好好想一下刚才的圆盘-128 -1 = -129  转换过来就是127
//知道他从右下转到右上遇见了字符'0' ,他就停止了

Wrong idea: the array defined by a of char type is stored in -1, -2 …-1000, but strlen does not meet \0, so the size of strlen is a random value

unsigned char type problem

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

The result will also be an endless loop. Because the maximum size of unsigned char is only 255, so it keeps meeting the conditions inside the loop body, and it keeps printing "hello world"

Three. Storage of floating-point type in memory

int main()
{
    
    
	int n = 9;
	float* pFloat = (float*)&n;// float* 访问的也是4个字节的空间大小
	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;
}

Insert picture description here
Analysis: For the pointer pFloat, it thinks that the complement of int = 9 stored in memory should be the floating point type
00000000 00000000 00000000 00001001
0 00000000 00000000000000000001001
Restore it back: (-1)^ 0* 0.00000000000000000001001 * 2^-126
unlimited Close to 0, so it prints out 0.000000

*pFloat = 9.0 is stored in the form of
(-1)^ 0 * 1.001 * 2^3 and then store it in the memory. M=3 plus 127 to convert to binary
0 10000010 00100000000000000000000-the calculated value thinks this is the complement, and the sign Bit means positive.
Note: In
Insert picture description here
the case of 32 bits:
Insert picture description here

int main()
{
    
    
	float f = 5.5;
	//5.5
	//101.1
	//(-1)^0 * 1.011 * 2^2
	//S=0
	//M = 1.011
	//E =2
	//E在内存中真正的存储方式是要加127的  把129转化为二进制数
	// 0 10000001 011 00000000000000000000(补齐23位M)一共32位,这才是真正的在内存中存储的二进制序列
	//0x 40 b0 00 00 以16进制的形式展现内存
}

64-bit case The case where the
Insert picture description here
exponent E is taken out of the memory:
1. When E is not all 0s or not all 1s: -127 is required for 32 bits, and -1023 is required for 64 bits to get its real E value
2. E is all 0: For this case, if you think he has added 127 and the result is all 0, it means -127, which is a very small number
0 00000000 01100000000000000000000
0.011 * 2^-126
for E In the case of all 0s, we stipulate that M does not need to be complemented by 1 when restoring, and E is also directly changed to a fixed value of 1-127 3. When
E is all 1s: E+127 = 255, so the original E=128
1. The number xxx * 2^128 is too large to be calculated, so it is not considered.
Insert picture description here

Guess you like

Origin blog.csdn.net/MEANSWER/article/details/109692179