如何将16位2进制数写成内存地址_c++ c语言 进制、原反补码、输入输出函数

c语言基础语法 

进制、原码、反码、补码、输入输出函数

进制

1、十进制转二进制

如:666 转成二进制,采用除二反向取余,每次除以二,若每次可以被2整除,则为0,若无法整除,则取余为1,余数继续除二,直到为0

4436e4025fc7b6313e1667030013f47a.png

则得到结果:1010011010, 代码实现如下:

#include
int main(void){
    int i=0,n,a[32];
    printf("请输入一个十进制整数.\n");
    scanf("%d",&n);
//    除二反向取余
    while (n>0)
    {
        a[i]=n%2;
        i=i+1;
        n=n/2;
    }
    printf("十进制整数转换为二进制数是:\n");
    for(i--;i>=0;i--)
        printf("%d",a[i]);
    printf("\n");
    return 0;
}

720ea8988eb60cc8576aa4a8802ca995.png

2、二进制转十进制

采用了当取幂,与之相乘的算法:如:110101

则从右往左为低为到高位,则该十进制数为:

e3ed42e2b08c482e8a35420ea1be7cc4.png

代码实现如下:

#include
int main(){
 char ch;
 int a=0;
    //遍历获取
 while(ch=getchar(),ch!='\n')
  a=a*2+(ch-'0');
 printf("%d\n",a);
 return 0;
}

6af2c7dc320b60d9ec9a74f981171362.png

3、八进制转二进制

方法:展开法

056:5 ==》 101, 6 ==》110 则:

101110

05326:5==》101, 3==》011,2==》010,6==》110

101011010110

4、八进制转十进制

采用类似二进制转十进制的方法。

1507

5、十六进制转十进制

16进制数的第0位的权值为16的0次方,第1位的权值为16的1次方,第2位的权值为16的2次方……

所以,在第N(N从0开始)位上,如果是数 X (X 大于等于0,并且X小于等于 15,即:F)表示的大小为 X * 16的N次方。

例:2AF5换算成10进制:

用竖式计算:

第0位:5 * 16^0 = 5

第1位:F * 16^1 = 240

第2位:A * 16^2= 2560

第3位:2 * 16^3 = 8192

直接计算就是:

5 * 16^0 + F * 16^1 + A * 16^2 + 2 * 16^3 = 10997

6、十六进制转二进制

由于在二进制的表示方法中,每四位所表示的数的最大值对应16进制的15,即16进制每一位上最大值,所以,我们可以得出简便的转换方法,将16进制上每一位分别对应二进制上四位进行转换,即得所求:

例:2AF5换算成2进制:

第0位:(5)16 = (0101) 2

第1位:(F)16 = (1111) 2

第2位:(A) 16 = (1010) 2

第3位:(2) 16 = (0010) 2

得:(2AF5)16=(0010.1010.1111.0101)2

代码输出方法

8beda9da5fa3bee9d20ba606f38d43ec.png

9c068e1210553b605ad24dcbb96c9807.png

C语言的格式化输出能直接将十进制数转成8进制或者16进制:

#include 

int main(void){
   int a = 156;
 printf("10进制显示:%d\n",a);
 printf("8进制显示:%o\n",a);
 printf("16进制显示:%x\n",a);
 return 0;
}

也可以使用十六进制数转成十进制或者八进制:

#include 
int main(void){
 int b = 0x4c;
 printf("10进制显示:%d\n",b);
 printf("8进制显示:%o\n",b);
 printf("16进制显示:%x\n",b);
 return 0;
}

内存数值存储方式

预备知识:

一个Bit位即为一个二进制位

一个字节1B = 8Bit

1KB = 1024B

1MB = 1024KB

1GB = 1024MB

1TB = 1024GB

1、机器数

一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1.

比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。

那么,这里的 00000011 和 10000011 就是机器数。

2、真值

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1
一、原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

原码是人可直接理解最简单的二进制码的理解方式。

[+1]  ==》 原 = 0000 0001

[-1]   ==》 原 = 1000 0001

区别在最开头的0和1的区别0表示正数,1表示复数

第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:

[1111 1111 , 0111 1111] == [-127 , 127]

二、反码

反码的表示方法是:

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

[43] = [00101011]原 = [00101011]反

[-43] = [10101011]原 = [11010100]反

三、补码(重要)

补码是现今计算机采用的存储形式。

  • 对于正数,原码、反码、补码相同。
  • 对于负数,其补码为它的反码加1。
    • 补码符号位不动,其他其他位求反,最后整个数加1,得到原码。

如下例子:

[+1] = [00000001]原 = [00000001]反 = [00000001]补

[-1] = [10000001]原 = [11111110]反 = [11111111]补

补码的意义

我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.

于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:

计算十进制的表达式: 1-1=0

但是计算由原码如下,用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

为了解决原码做减法的问题, 出现了反码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1)

= [0000 0001]原 + [1000 0001]原

= [0000 0001]反 + [1111 1110]反

= [1111 1111]反 = [1000 0000]原

= -0

发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.

于是补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1)

= [0000 0001]原 + [1000 0001]原

= [0000 0001]补 + [1111 1111]补

= [0000 0000]补

=[0000 0000]原

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值。

补码计算例子

43 - 27 = 43 + (-27)

= [00011011]原 + [10011011]原

= [00011011]补 +  [11100101]补

= [00010000]补 = [00010000]原

= 15

四、数据溢出
当出现计算溢出的时候:
  • 两正数加,变负数,上溢(大于机器所能表示的最大数)

  • 两负数加,变正数,下溢(小于机器所能表示的最小数)

一般是char类型的溢出:

#include 

int main(void){
 char ch = 127;
 printf("ch = %d\n",ch);
 ch = 127 + 1;
 printf("ch + 1 = %d\n",ch);
 ch = 127 + 2;
 printf("ch + 2 = %d\n",ch);
 return 0;
}

ea7d54b6303a081ded845516de65a232.png

因为char类型本身的数据容量很少,只有8Bit的长度,所以很容易出现数据溢出的现象。

五、类型限定符
extern

    表示声明,没有内存空间,无法提升。

const

    限定一个变量变为只读变量。对象的类型如果采用了限定符 const,则该对象就是常量。在定义该对象之后,程序无法修改它。

volatile

    防止编译器优化代码。对象的类型如果采用了限定符 volatile,则该对象可以被其他进程或事件修改。关键字 volatile 告诉编译器在每次使用该对象值时,都要重新读取它,即便程序本身自上一次获取后再没有修改过它的值。这种限定符通常用于硬件接口编程,以防止变量值被外部事件修改后,未能及时更新。

register

    定义一个寄存器变量。

输入输出的一些知识点

一、putchar与getchar函数
  • getchar() 用于读取用户从键盘输入的单个字符,它有一个整型的返回值,当发生读取错误的时候,返回整型值-1,当读取正确的时候,它会返回用户从键盘输的第一个字符的ASCII码,当程序调用getchar时,运行程序时就等着用户从按键输入,用户输入的字符被存放在键盘缓冲区中.

    直到用户按回车为止(回车字符也放在缓冲区中),当用户键入回车之后,getchar才开始从输入流中每次读入一个字符,输入的字符不只一个的时候,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完之后,才等待用户按键,getchar函数输入数字也按字符处理,单个的getchar函数输入多于一个字符时,只接收第一个字符。

  • putchar()向终端输出一个字符。其格式为putchar(ch),其中ch可以是被单引号(英文状态下)引起来的一个字符,可以是介于0~127之间的一个十进制整型数(包含0和127)(超过127就不是ASCII码了),也可以是事先用char定义好的一个字符型变量当c为一个被单引号(英文状态下)引起来的字符时,输出该字符(注:该字符也可为转义字符),当c为一个介于0~127(包括0及127)之间的十进制整型数时,它会被视为对应字符的ASCII代码,输出该ASCII代码对应的字符;

    当c为一个事先用char定义好的字符型变量时,输出该变量所指向的字符。当整型变量ch超出8位变量的范围时,ch则会变强制转化为8位变量(即取其低八位传过去输出),当为负数的时候,由于计算机存储负数是用补码表示的,所以传过去的二进制补码也被当做正数处理,也是取其低八位

    getchar()和putchar()函数包含在头文件stdio.h中,使用时需包含此头文件

#include 

int main(void){
    char ch;
    ch = getchar();
    printf("输出getchar()所输入的数据:\n");
    putchar(ch);
    return 0;
}

68c2f8922a5c7cbdc7ae2af2bb4eb2b7.png

2、scanf函数

scanf 的功能用一句话来概括就是“通过键盘给程序中的变量赋值”。

scanf("输入控制符", 多个参数);

功能:将从键盘输入的字符转化为“输入控制符”所规定格式的数据,然后存入以输入参数的值为地址的变量中。

#include 

int main(void){
 int a;
 printf("输入a =");
 scanf("%d",&a);
 /* &表示取出变量a的地址,描述a的空间在哪
    %d 则是表示该a是以该格式存入,输入浮点数也将以整数形式
 */
 printf("a = %d\n",a);
// printf("输入ch =\n");
// char ch1,ch2,ch3;
// scanf("%c%c%c",&ch1,&ch2,&ch3);
// printf("ch = %c\n",ch1);
// printf("ch = %c\n",ch2);
// printf("ch = %c\n",ch3);
 return 0;
}

多次输入的话,可以同时多数据:但是只能接受指定的数据量

scanf("输入控制符", 数组参数);

允许数组格式接受整串

#include 

int main(void){
 char str[10];   
 /*定义一个数组,用来接收用户输入的字符串。
 但是注意最多只能10字节,超出会无法接受多余的数据
 但是一般情况c程序会补充栈*/
 scanf("%s", str);  //变量名要取地址传递scanf,数组名本身表示地址,不用 &
    printf("%s",str);
    return 0;
}

如上helloguojia中,虽然全部打印出来了,但是只有“helloguoji”受到保护,而“a”不受保护,具有安全隐患。若存在存储空间不足,就会被弹出,出现数据的异常。

bbe522d37d72574b6811326896b45c31.png

4263240686555513d3ea9fb2c8a4759f.png

注意:scanf 函数碰到字符串时,碰到空格和换行会自动终止。

026ed2ec272cc19777e2e73268efb7f9.pnga9cacfb56c8300f3234f072b7aadae2c.pnga9cacfb56c8300f3234f072b7aadae2c.png

往期文章

2020-8-19

  • C++语法1、类与对象

  • c++语法2、c执行-命名空间-输入输出

  • c++ 3、语法 数据类型

  • c++ 4、语法 数组

  • c++  c语言- 概述

  • c++  c语言 - 控件及概述补充

  • c++  c语言 - 数据类型

图 | 郭嘉

文 | 郭嘉

9a379a6fae6ba120af82c379f808bc91.png

扫码关注桔梗与少年

微信号 : if-u-remembers

新浪微博:桔梗与少年

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当我们将一个double类型的转换成二进制时,需要考虑到浮点的表示方式以及二进制运算的规则。 首先,浮点的表示方式采用了IEEE 754标准,它将一个双精度浮点分为三个部分:符、指和尾。 符用于表示的正负,1表示负,0表示正。 指用于表示的指部分,采用偏移码表示。在双精度浮点中,指占11。 尾用于表示的小部分,采用补码表示。在双精度浮点中,尾占52。 要将一个double类型的转换成二进制,首先要确定符。如果是正,则符为0,如果是负,则符为1。接下来,要确定指和尾的值。 指的值等于的指加上一个偏移值(在双精度浮点中为1023),然后转换成二进制。 尾的值等于的小部分转换成二进制。 最后,将符、指和尾组合在一起,就得到了该double的二进制表示。 需要注意的是,由于尾有52,而二进制只能精确表示有限个,所以转换成二进制后可能会有一定的误差。 总结起来,将一个double类型的转换成二进制需要确定符、指和尾的值,并将它们组合在一起。 ### 回答2: 要将一个C语言中的double类型转换为二进制,可以使用union联合类型来进行操作。首先,我们需要定义一个double类型的变量,然后创建一个联合类型,其中包含一个double类型的成员变量和一个unsigned long long类型的成员变量。 接下来,将double类型的变量赋值给联合类型的double成员变量。然后,我们可以利用联合类型的unsigned long long成员变量来获取该double类型的二进制表示。 具体步骤如下: ```c #include <stdio.h> union DoubleToBinary { double d; unsigned long long ll; }; void printBinary(unsigned long long num) { for (int i = 63; i >= 0; i--) { printf("%d", (num >> i) & 1); } } int main() { double num = 3.14; union DoubleToBinary dtb; dtb.d = num; printf("二进制表示为:"); printBinary(dtb.ll); return 0; } ``` 在上述代码中,首先定义了一个DoubleToBinary的union类型,其中包含了一个double类型的成员变量d和一个unsigned long long类型的成员变量ll。 然后在main函数中,定义了一个double类型的变量num,并将其赋值为3.14。接着,将num赋值给dtb的d成员变量。 最后,调用printBinary函数,参为dtb的ll成员变量,打印出该double类型的二进制表示。 运行以上代码,输出结果为:二进制表示为:010000000000100100011110101110000101000111101011100001010001 帮助 ### 回答3: 将double类型的值转换为二进制需要进行以下步骤: 1. 首先,将double类型的值转换为64的二进制表示。这可以通过IEEE 754标准来完成,该标准规定了浮点的二进制表示方法。 2. 取得这64个二进制的最高,这一表示该double值的符。0代表正,1代表负。 3. 将剩余的63进制分组,其中11表示指,剩下的52表示尾。 4. 将指转换为10进制值,通过指与尾的组合,可以确定double值的大小。 5. 将尾中的每个二进制转换为10进制值,得到double值的精度。 6. 将步骤2到5得到的值组合在一起,即为该double值的二进制表示。 需要注意的是,由于double类型的值的精度较高,转换为二进制后可能会非常长。为了简化表示,通常只保留一定的。 总结起来,将double类型的值转换为二进制需要进行IEEE 754标准的转换,并按照指和尾规定的置来确定double值的大小和精度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值