一.整型在内存中的存储
①基本的数据类型:
我们都知道C语言有这么几种数据类型,那么在C语言为什么要分成这几种类型,类型区分的意义在哪里呢?
据笔者理解,类型的划分对于计算机来说它有两种含义:
①它肯定限定了这个类型开辟了多大的空间,限定了它的使用范围。
②它告诉计算机看待这个数据的视角。
1.1整形的原反补
我们都知道计算机中的整数有三种2进制表示方法,即原码、反码和补码。
原码:直接将数值按照正负数的形式翻译成二进制就可以得到原码。(正整数不需取反加1得补码,原码即补码)
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
看到这里,有xd可能要问,为什么负数要进行这么一番操作,直接像正整数一样取原码进行加减不方便吗?
我们简单举个例子,以int类型为例,如果仅原码进行计算,我们可以得出9+(-10)这个答案是-19,这显然是错误的。而按照补码进行计算,
显然利用补码可以得到正确的答案。那么从这可以先得出一点,即对于整形来说:数据存放内存中其实存放的是补码。还有一个点笔者补充一下:CPU只有加法器,那么统一为补码也方便计算。那么这么牛批的方法是怎么发明的,笔者也不清楚,只能说先辈真的厉害,吃水不忘挖井人,致敬先辈!!!
1.2整型的大小端存储
知道了整型在内存中是以补码的方式存储的,那么整型是否按照我们所设想的比如int a =20 ;16进制为:0x00000014 这样存储的呢?(在监视里内存是以16进制展现如何存储的)
通过vs的调试,我们可以发现它与我们设想的不一致,顺序并非如此,而是相反的,这又是为什么呢?我们就不得不说到大小端存储的概念了。
大端(存储)模式:是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址 中;
小端(存储)模式:是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地 址中。
其实大小端本身没有优劣之分,只是依据不同的硬件,机器的存储模式会有所不同而已。比如说我们常用的 X86 结构是小端模式,而 KEIL C51 则 为大端模式。很多的ARM,DSP都为小端模式。这和机器有关。
掌握这个可以让我们对计算机的底层逻辑了解的更清楚。下面介绍一道百度笔试题。
题目:请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。
我们如何判断当前机器是如何存储的呢?以一个数比如说1,我们首先看一下这个数的存储形式。
0x00000001 根据大小端的概念,我们如果只取这个整形的最后两字节,来判断是1还是0就可以判断当前机器是大端还是小端存储。清楚了这件事就好办了。当然,我们这里可以强制类型转换和利用共用体两种方式来判断。
笔者会用两种方式实现这道题目:
强制类型转换:
#include <stdio.h> int check_sys() { int i = 1; return (*(char *)&i); } int main() { int ret = check_sys(); if(ret == 1) { printf("小端\n"); } else { printf("大端\n"); } return 0; }
共用体:
int check_sys() { union { int i; char c; }un; un.i = 1; return un.c; } int main() { int ret = check_sys(); if(ret == 1) { printf("小端\n"); } else { printf("大端\n"); } return 0; }
可以看到笔者当前的机器是小端存储的。
1.3无符号型和有符号型
无论是考试还是面试,笔试,我们总会碰到一些类型转换的题目,这些题目本质上还是和计算机的存储挂钩的。下面笔者就通过几个题目和大家简要阐述一下这方面的一些坑。
各位可以自己看答案之前,想一下自己认为答案是什么,然后看一下答案,说不定会让你大吃一惊呢!
①
这段代码可能有不少朋友会觉得c应该是-1.那么在这里首先可以说明一下,无符号型数是没有负数的,因为它没有符号位。所以对于char类型来说,它的范围就是0-255.而-1的补码是11111111,所以值为255。(对了,这里还涉及到了整型提升,不过对于无符号型的char来说,还是高位补0,所以值还是为255)
②
相信这个代码得结果会令不少朋友大吃一惊,但是如果考虑到整型提升和打印类型的话,那么就可以分析得到个数。
③
这个数也是同样的.
④
这个结果是什么呢?可能通过基本的推断读者都可以猜测不可能简单的到i=0会停下来,因为unsigned int 类型的值是大于等于0的,所以我们进一步分析。当i=0然后再-1的情形。
结果也如我们所推断那样。这里我用了一个Sleep睡眠函数,让它再打印后会停止1000毫秒,方便我们观察,它的头文件是#include<windows.h>.
⑤
这个函数会呈现怎样的结果呢?首先读者可能会纳闷,为什么会有strlen这个函数来计算整型数组,strlen不是计算字符串的长度吗?本质上strlen是碰到'\0'停止,而'\0'的ASCII值为0,所以说我们只要判断在什么时候a数组指向的值为0即可。