补码原理
1、补码
//嵌入式开发需要了解补码
#include<stdio.h>
void main(){
int a = -1; //-1 在int 范围内,赋值实际上是赋的内存地址中二进制的值
printf("%x\n",&a); //&a的内存地址是0x0018FA88通过改地址找到内存中的值是ff ff ff ff
/* -1 内存中的值为 ff ff ff ff
-1的补码二进制为:1111 1111 1111 1111 1111 1111 1111 1111
-1的反码二进制为:1111 1111 1111 1111 1111 1111 1111 1110 -1
-1的原码二进制为:1000 0000 0000 000 0000 0000 0000 0001 取反
*/
printf("%d,%u\n",a,a); //output: -1,4294967295
/*%d按照有符号的十进制输出,-1在[-2^15,2^15-1]内,内存中二进制的补码值为1111 1111 1111 1111 1111 1111 1111 1111,
首位1代表符号位,求出其原码,1000 0000 0000 000 0000 0000 0000 0001,输出-1,
%u按照无符号的十进制输出,-1不在[0,2^32-1]内,但-1的内存中二进制的补码值为1111 1111 1111 1111 1111 1111 1111 1111
无符号位,正数的原码与补码一样,求出其原码 1111 1111 1111 1111 1111 1111 1111 1111,输出4294967295,*/
int b = 4294967295; //4294967295不在int范围内,直接把二进制赋值给b,有系统声明的变量去做解析和解释
//4294967295的二进制形式为:1111 1111 1111 1111 1111 1111 1111 1111
//把上面的二进制直接赋值给b,printf()函数的本质是按照指定格式%d或%u输出二进制的值,不管二进制是什么数
//%d按照有符号的十进制整数去解析输出就是-1,%u按照无符号十进制的整数输出4294967295
printf("%d,%u\n", b, b); //output: -1,4294967295
unsigned int c = -1; //-1 不在unsigned int 范围内
unsigned int d = 4294967295; // 4294967295在unsigned int 范围内
/* 数据复制本质上是二进制的赋值,数据范围内保证正确,数据范围外不保证正确
4294967295的内存中的二进制形式为:1111 1111 1111 1111 1111 1111 1111 1111
-1 内存中的二进制形式为:1111 1111 1111 1111 1111 1111 1111 1111
两个数在内存中存储的二进制是一样的,在程序运行时,按照各自声明的变量进行解析
c尽管是无符号整型,没有负数,但按%d有符号解析,32位1转换成原码就是-1,输出-1
按%u解析,也是无符号的,32位都是数据位,输出4294967295
d尽管是无符号整型,没有负数,但是按%d有符号解析,32位1转换成原码就是-1,输出-1
按%u解析,也是无符号的,32位都是数据位,输出4294967295
*/
printf("%d,%u\n", c ,c);//output: -1,4294967295
printf("%d,%u\n", d, d);//output: -1,4294967295
//以下内容没有搞懂,以后再看
int e = 217483648; //217483648 不在int范围内
/*2147483647的内存中的二进制形式为:0111 1111 1111 1111 1111 1111 1111 1111 最大值
2147483648的内存中的二进制形式为:1000 0000 0000 0000 0000 0000 0000 0000
1、%d解析 带符号解析
补码 2147483648的内存中的二进制形式为:1000 0000 0000 0000 0000 0000 0000 0000 也就是补码 首位1表示该数是负数
反码 2147483648的内存中的二进制形式为:1111 1111 1111 1111 1111 1111 1111 1111 减去1,符号位不变 首位1表示该数是负数
原码 2147483648的内存中的二进制形式为:1000 0000 0000 0000 0000 0000 0000 0000 取反 符号位不变 首位1表示该数是负数
*/
printf("%d,%u\n", e, e);//output:-2147483648,2147483648
int f = -217483648; //-217483648 不在int范围内
printf("%d,%u\n", f, f);//output:-217483648, 4077483648
char h = 255; //-255 不在char范围内
printf("%d,%u\n", h, h);//output:-217483648, 4077483648
/*
1111 1111
结论:赋值和解析是分开的,赋值的本质是赋二进制的值,解析按照%d,%u去解析
*/
getchar();
}
%d是有符号整型输出 有范围限制,INT_MIN-INTMAX
%u是无符号整型输出 有范围限制,0-UINTMAX
按照%d解析
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
void main(){
printf("%d,%u", UINT_MAX, UINT_MAX); //-1,4294967295
/* UINT_MAX 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
按照%d解析 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110
1000 0000 0000 0000 0000 0000 0000 0000 0000 0001 原码是 -1
*/
system("pause");
}
同样的二进制数值存储形式,不同的解析方法,其结果也会不一样
//#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
void main(){
int x = 4294967295; //4294967295已经超过了int的范围
//赋值本质上是赋值二进制的值,即使该数已经超过了其表示范围,所以是直接把数值在计算机的表现形式(补码的形式)赋值给&x,
//4294967295内存中的存储形式:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
//按照%d解析,有符号解析,首位1代表负数,内存中的二进制则是负数的存储形式,负数在内存中是以补码的形式存放
//得转换成程序中的原码形式:
// 符号位不变,-1成 反码 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110
//符号位不变,取反成原码 1000 0000 0000 0000 0000 0000 0000 0000 0000 0001
//即为-1;
//按照%u来解析,内存中的存储形式:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
//首位不是符号位,都是数值位,即是4294967295
printf("%d,%u",x,x); //-1,4294967295
int y = -1;
//赋值本质上是赋值二进制的值,所以是直接把数值在计算机的表现形式(补码的形式)赋值给&y,
//-1内存中的存储形式:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
// 按照%d和%u解析,同以上原理一样。
printf("%d,%u", x, x); //-1,4294967295
//内存中同样的二进制,解析不一样,结果也会不一样
system("pause");
}
无符号int也一样
//#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
void main(){
unsigned int x = 4294967295;
//赋值本质上是赋值二进制的值,所以是直接把数值在计算机的表现形式(补码的形式)赋值给&x,
//4294967295内存中的存储形式:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
//按照%d解析,有符号解析,首位1代表负数,内存中的二进制则是负数的存储形式,负数在内存中是以补码的形式存放
//得转换成程序中的原码形式:
// 符号位不变,-1成 反码 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110
//符号位不变,取反成原码 1000 0000 0000 0000 0000 0000 0000 0000 0000 0001
//即为-1;
//按照%u来解析,内存中的存储形式:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
//首位不是符号位,都是数值位,即是4294967295
printf("%d,%u",x,x); //-1,4294967295
unsigned int y = -1;
//赋值本质上是赋值二进制的值,即使该数已经超过了其表示范围,所以是直接把数值在计算机的表现形式(补码的形式)赋值给&y,
//-1内存中的存储形式:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
// 按照%d和%u解析,同以上原理一样。
printf("%d,%u", x, x); //-1,4294967295
//内存中同样的二进制,解析不一样,结果也会不一样
system("pause");
}
/*
short int(long) long long
%hd %d %lld
%d 无符号10进制 10 10
%o 无符号8进制 010 8
%x 无符号16进制 0x10 16
%d —— 以带符号的十进制形式输出整数
%o —— 以无符号的八进制形式输出整数
%x —— 以无符号的十六进制形式输出整数
%u —— 以无符号的十进制形式输出整数
%c —— 以字符形式输出单个字符
%s —— 输出字符串
%f —— 以小数点形式输出单、双精度实数
%e —— 以标准指数形式输出单、双精度实数
%g —— 选用输出宽度较小的格式输出实数
*/

浙公网安备 33010602011771号