c语言里的一些底层行为

文章目录

  • 1.整数溢出
    • 补充有关整数范围的知识
  • 2.有关char的底层行为
  • 3.有关于段错误的一些东东
    • **例子1:
    • **例子2**
  • 4.为什么浮点数多打印几位发现不能精确表示?
  • 5. int float double的转化中出现的问题
    • *1.该问题的解决**
    • **2.如果一个正常的int型数转成float会怎样?**
    • **3.如果一个处在float型空洞的int型数据转成float会怎样?**
  • 6. 用float,int,short来输出字符串

1.整数溢出

c语言里的一些底层行为_第1张图片
在这里插入图片描述
为什么后面输出的结果这样了呢?
50000*50000实际结果应该为2500000000。转化为16进制为9502f900.
结果在终端的16进制储存结果如图将9502f900转化为二进制:10010101000000101111100100000000
由于首位应该是符号位,所以计算机识别的时候把首位作为符号位,这是一个负数,所以是补码,原码是1(符号位)101010111111010000011100000000,将这个数转成十进制结果为-1794967296.

补充有关整数范围的知识

int的范围是-2147483648~2147483647。
计算方法如下:
计算机中32位int类型变量的范围,其中int类型是带符号整数。

正数在计算机中表示为原码,最高位为符号位:
2147483647:
原码为0111 1111 1111 1111 1111 1111 1111 1111
所以最大的正整数是2147483647

负数在计算机中表示为补码,最高位为符号位:
-1:
原码为1000 0000 0000 0000 0000 0000 0000 0001,
补码为1111 1111 1111 1111 1111 1111 1111 1111

-2147483647:
原码为1111 1111 1111 1111 1111 1111 1111 1111,
补码为1000 0000 0000 0000 0000 0000 0000 0001

所以最小的负数是-2147483647吗?错,不是
在二进制中,0有两种表方法。
+0的原码为0000 0000 0000 0000 0000 0000 0000 0000,
-0的原码为1000 0000 0000 0000 0000 0000 0000 0000,
因为0只需要一个,所以把-0拿来当做一个最小的数-2147483648。

-2147483648的补码表示为1000 0000 0000 0000 0000 0000 0000 0000,在32位没有原码。

注意,这个补码并不是真正的补码,真正的补码是1 1000 0000 0000 0000 0000 0000 0000 0000,溢出。
所以带符号32位int类型整数为-2147483648~2147483647

2.有关char的底层行为

c语言里的一些底层行为_第2张图片
输出都为-128 -128?
Char在c中只占一个字节,因为有符号字符型其范围为-128~127
127用二进制表示为:0111 1111,
128表示为1000 0000,这里发生溢出,因为第一位为1,为符号位,表示负数,即-128

3.有关于段错误的一些东东

**例子1:

**

因为它尝试操作地址为0的内存区域,而这个内存区域通常是不可访问的禁区,当然就会出错了。

例子2

c语言里的一些底层行为_第3张图片
unsighed不能为负数,这里len-1就违背了,所以发生段错误

4.为什么浮点数多打印几位发现不能精确表示?

在 C 中,如下代码:
float e = 1.1110999f;
printf(“1.1110999f 打印真实为:%f” , e);
会输出:1.1110999f 打印真实为:1.1111
深入分析其原因,并给出判断一个浮点数是否能精确表示的思路
懒得打字了,自己在终端去试试吧。

5. int float double的转化中出现的问题

例 1: int i=Int32.MaxValue;
float f=i;
int j= (int)f; 此时如果判断(i==j),将返回 false;
*

1.该问题的解决*

c语言里的一些底层行为_第4张图片
执行完float f=i后的结果是(红线部分)。
为什么呢?f的阶码是10011110,转化为10进制是 158,减去127就是31,f=2∧31.因为i的2∧31-1应该是float无法精确表示的,所以只能表示为接近它的2∧31。

执行完int j= (int)f后,j中
在这里插入图片描述
其实就是所谓的2^31,但是溢出了,打印其值应为-2147483648.

2.如果一个正常的int型数转成float会怎样?

在这里插入图片描述
在这里插入图片描述F:1.01*2^2=5(十进制)

3.如果一个处在float型空洞的int型数据转成float会怎样?

考虑float型从8388608开始不能再表示小数了:
0(符号位) 10010110(阶码位) 0…0(23个0) 这里的阶码已经达到了23
所以不妨从这个往上开始找。
会用最接近的数来表示。
c语言里的一些底层行为_第5张图片
例2. double d1 = 0.6;
float f = (float)d1;
double d2 = f; 此时判断 d1 == d2,同样会返回 false

6. 用float,int,short来输出字符串

现有如下代码:
#include int
main() {
float a[3]={1143139122437582505939828736.0,76482007234779498639230238720.0,9.222452464e-39};
printf("%d\n", sizeof(float));
printf("%s\n",a); return 0; }
请在 GCC 中运行以上代码,你看到了什么运行结果?请演示并解析,为什么打印一个浮点数组,却会输出一段字符? 仿照选题一中的代码,定义一个整型数/短整型数组,应该如何现?对如下代码你预估的执行结果是什么?实际 GCC 中执行结果是什么?请解析。

运行结果:
在这里插入图片描述
sizeof(float)的大小是4个字节,
那么a[3]就是12个字节(即内存中有一个连续的内存,长度12字节)。
这12个字节中,有3个数字,每个数字长度4字节。

• 其中第一个数字1143139122437582505939828736.0,
• 它在内存中的16进制数据是:48 65 6C 6C (小段法 内存里面 这里是ieee表示浮点数)
• 另外两个数字76482007234779498639230238720.0, 9.222452464e-39,在内存中的数据(16进制)是:
• 6F,20, 77,6F 和 72, 6C, 64, 00
• 而Hello world用16进制表示为48 65 6C 6C 6F 20 77 6F 72 6C 64 00
• 两者相同,所以可以打印出来
c语言里的一些底层行为_第6张图片
通过gdb调试,打印出Hello world后查看float数组首地址0xbffff2b4,再查看地址里面储存的12个字节的内容,正好是前面所说的数据

• 如果用int数组来表示为int a[3] = {1819043144,1870078063,6581362};
• 1819043144整数转化为16进制为48 65 6C 6C
• 同理,剩下的数字可以表示剩下的字符
c语言里的一些底层行为_第7张图片
• 用short数组来表示为short a[6] = {25928,27756,8303,28535,27762,100};
• 25928整数转为十六进制在内存中为48 65
• 27756整数转为十六进制内存中为6C 6C
• 同理,剩下的数字可以表示剩下的字符

c语言里的一些底层行为_第8张图片

你可能感兴趣的:(c语言里的一些底层行为)