进一步了解C

0.序言

嗯,这几天了解了一点点的C语言的内部知识,在这记录一下,有错处还请大佬指出,我一定会好好的更正的。我所写是根据我的笔记所写,如果想看我的笔记链接我放在这了->flowus<-。

1.整形的存储

整形的存储,计算一般以二进制的补码形式进行。而对于正数原反补相同,而对于负数,其补码是原码取反+1,而在存储的过程中,我们绕不开小端存储以及大端存储,而在如何验证所使用的是大端机器还是小端机器的过程,我想当然了,在这进行一个分享。

大小端的原理其实也不难,对于一个整型变量,他在内存中有四个字节的空间,我们在平常调用时,是从它最低的地址开始的,而将一个数放到变量中,相当于由四个字节构成这个数,每个字节放一些值,而在构成的过程存在一定的顺序,这就是大小端了,对于一个数(写成十六进制好些)左边就是高位,右边就是低位,如果高位在低地址处那么就是大端存储,反之就是小端存储

差不多就这样,你们来看看我写的吧是咋判断大小端的吧!

 

 

来谈谈我当时的想法吧,那时我就是想你机器排完序后我在截断,那不是也能判断了。 事实上在将int强转char后它只会保留一个字节,其他的舍弃,他就一个字节了,根本不用排序,直接放就行了,其实大小端的基础是在你的字节大于1个的时候才进行的

2.算术转换

算术转换:用于在进行算术运算或比较运算时将操作数转换为一个共同的类型,以确保操作的有效性和结果的一致性。

通常就是int和float进行计算,把int转为float,然后计算的结果也是float的类型。

整型提升就是当char或者short不足以存储下一个值时,但这个值可以被int存储,那么就会提升为int。

浮点提升当参与运算的操作数中有浮点数时,较低精度的浮点数(如float)会被提升为较高精度的浮点数(如double)。

//算术转换我这是查了一些资料,可能不够确,还出指出///

 下面是一些例子

///对了,如果应该没错的话整数常量一般是int类型

char  n = 127;
char  m = n + 5;
printf("%d\n", m);

 127为整数原反补相同。

补码为:0000  0000  0000  0000  0000  0000  0111 1111

当它赋给字符变量n的时候,由于变量n为字符指针,那么就会反生截断

n:0111 1111

n和int类型的常量进行运算时,会进行整形提升,对于原来的n为有符号的char,高位补符号位,符号位为0。

n就是:0000  0000  0000  0000  0000  0000  0111 1111

5就是:0000  0000  0000  0000  0000  0000  0000  0101

n + 5为:0000  0000  0000  0000  0000  0000  1000  0100 

m发生截断1000 0100

然后打印是以有符号整形打印,那么他原本是char那么会进行提升为int

原本是有符号的char那么高位补符号位,符号位是1,那就补1

1111 1111 1111 1111 1111 1111 1000 0100这是补码,有符号的要的到原码取反加1

1000 0000 0000 0000 0000 0000 0111 1100

值为 -124

  unsigned char a = 200;
  unsigned char b = 100;
  unsigned char c = 0;
  c = a + b;
  printf(“%d %d”, a+b,c);

200对应二进制的补码为:0000 0000 0000 0000 0000 0000 1100 1000

赋给无符号char的变量a:1100 1000

100对应的二进制补码为:0000 0000 0000 0000 0000 0000 0110 0100

赋给无符号char的变量b: 0110 0100

a 和 b相加时为300超过了unsigned char的范围,故先把a和b提升int的类型

a + b:0000 0000 0000 0000 0000 0000 1100 1000 + 0000 0000 0000 0000 0000 0000 0110 0100 = 0000 0000 0000 0000 0000 0001 0010 1100

然后截断c:0010 1100

printf("%d %d\n", a + b, c);第一个打印a和b会提升为int的类型,为300。第二个打印c是char类型,故会提升为int,因为c为unsigned  char高位补0,为:0000 0000 0000 0000 0000 0000 0010 1100 值为44

1.进行比较操作: 在进行比较操作时,有符号整数会被提升为无符号整数。

2.将有符号整数赋值给无符号整数变量。有符号的数会暂时性的提升为无符号,并把结果赋给无符号的变量。

这可能不够准确,有不对的地方还望指出哈。

3.signed  char和unsigned  char

signed  char:有符号的取值为-128到127。对于一个字节它的最高位是符号位,剩下的是数值位。

unsigned char:无符号的取值范围是0到255。不存在符号位。

 

有了char的概念下面我们来看看这题吧!


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

嗯,这题我也刚开始也错了,首先明确strlen是统计\0之前的字符,char是有符号的,它的范围-128~127;对了\0的ASCII码值就是0,字符0的码值是48,NULL的值就是十进制的0,好了那我们继续,从-1开始依次-2,-3,...,-128,127....1,0。当把十进制0输入后,对应的就是\0,好了那么这中间有多少个值呢,|-128| + 127  = 255,还有0,那么就是256个,除了0,那就255。

那我们在来看看这个

这两个都将陷入死循环,感觉都没错?为啥呢,我在这就不说了。 

4.浮点数的存储

 我举的例子可能不太准确。

2存进整形变量0x00 00 00 02

2存进字符变量0x40 00 00 00

可见它们存进内存的方式不同。虽然这个例子有些牵强,如果有错处还望指出,谢谢啦。

整形我们知道了下面就是浮点数的存储了。

浮点数的打印是打印V对应的十进制,V是这个数的原码,V = (-1)^S * M * 2^E,这的-1,和2是确定的,S,M,E是决定浮点数的值。 

S:在二进制中用一个bit位来定,是用来确定符号位,位置在最高位。

MS后8位(32位下),S后11(64位下)数值位是这个值写成二进制,但是要是科学计数法表示例如(1.011 * 2^3),省略1,取小数点后的值。011当你在拿出来的时候加上1就行了。

E:剩下的位,float(32位)24,double(64位)52原来的值加上127(32位),1023(64位),并用二进制存进去。

32位

浮点数的计算:

公式:

V = (-1)^S * M * 2^E

解释:

  1. S
  • 如果高位是1,那么S就是1。

  • 反之,如果高位不是1,那么S就是0。

  1. E
  • 如果E为全0,那么E的结果就是1-127(32位),1-1023(64位)。

  • 如果E为全1,或者其他的情况,那么E就是二进制的结果-127,这就是E

  1. M
  • 先写小数点,然后跟着剩下的位。

  • 看是否要进行加1。

  1. 计算结果:
  • 套用公式V = (-1)^S * M * 2^E得到浮点数的原码。
float  n = 3.25;
printf("%#x\n", n);

3.25对应的二进制整数位:11,小数位.01,连起来11.01

关于小数转二进制,是乘2如果是1,就计一,直到小数为0。

0.25 * 2 = 0.5,计.0

0.5* 2 = 1,计.01

3.25对应的二进制为11.01,下面我们写成公式的样子V = (-1)^S * M * 2^E  

11.01 = (-1)^0 * 1.101 * 2^1;

S:0   M:1.101   E:1

M,先取出1,待后面拿出时加上那么其二进制是101 0000 0000 0000 0000 0000 

S:0

E:1 + 127 = 128 二进制(无符号的)1000 0000

那么合起来就是0 1000 0000 101 0000 0000 0000 0000 0000 

0100 0000 0101 0000 0000 0000 0000 0000   0x:40 50 00 00

小端存进机器就是:0x:00 00 50 40

 

那么我们在来试试拿出来吧

机器是小端,我们拿出后是0x:40 50 00 00 

二进制:  0100 0000 0101 0000 0000 0000 0000 0000 

S: 0

E:128 - 127 = 1;

M:0.101 + 1 = 1.101

V = (-1)^0*(1.101)*2^1 = 11.01转换二进制1 * 2^1 + 1* 2^0 + 0 * 2^-1 + 1 * 2^-2 = 3.25

好了这就是我所理解的,有不对的还望指出,谢谢啦,对了,这个是结合我的笔记写的下面是我在flowus的笔记,点一下就可以跳转啦!!谢谢啦。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值