数据在不同的系统中存储方式也不同,分为小端存放、大端存放。其中小端存放指的是高位数在高地址,低位数在低地址。
那么如何检测大小端存放:
union Node {
short a;
char ch[2];
};
int main() {
Node x;
x.a = 0x0001;
if (x.ch[0] == 1) {
//小端
}
else {
//大端
}
return 0;
}
short sa = 0x0001;
char* sp = (char*)&sa;
if (*sp == 1) {
//小端
}
else {
//大端
}
问题:为什么要以补码形式存储呢?
因为计算机中处理器的运算形式只有一种加法,所有的运算都是通过加法来实现的,对于下面这个式子:
w = a - b
在CPU中其实是通过下面这个式子实现的
[x-y]补 = [x+(-y)]补 = [x]补 + [-y]补
举一个简单有趣的例子,对于下面这段代码,可以看出计算机是以补码的形式存储数据的:
for (char a = 0; a < 128; ++a) {
printf("%4d", a);
}
printf("\n");
对于上面这段代码中,a是char类型的字符,所占空间为一字节,一共八个比特位,所以其正数所能表示的范围是:
0000 0000 = 0
0111 1111 = 127
这个时候继续执行for循环,a++,变成了下面这个数值:
1000 0000 = -128
所以循环会一直循环下去,并且按照下面这个规律一直循环下去:
对于char和signed char,会保留最高位的符号位,也就是a++,会
0 => 127 => -128 => -1 => 0 => ···
对于unsigned char,会认为最高位的数字不为符号位,为数值,按照下面这个流程实现
如下面这段代码中,将char类型的转换给无符号整型和有符号整型,其多余位是如何扩充的?
char a = 5;
char b = -5;
int x = a;
int y = b;
unsigned int z = b;
printf("x = %d y = %d z = %d", x, y, z);
printf("x = %x y = %x z = %x", x, y, z);
那么下面来讲解,类型转换中的数据转换规则扩充或者缩小规则:
与其自身有关,如果这个小的整型变量为有符号数,那么对于多余的空余位置填补的是其符号位的值,如果是无符号数,那么扩充的是0。
对于上面那个程序,其运行结果为:
其原理如下图:
指的是虽然类型不同,但是系统却可以自动识别进行转换
数据类型转换有两种,隐式类型转换和显示类型转换
从上面这个图可以看出,在进行一些运算的时候,C语言编译器会自动的对一些数据类型进行相应的隐式转换,使其扩展成int型,然后对int类型的数据进行操作,比如下面这段代码,就是很好的体现:
char a = -5;
unsigned char b = 10;
if (a > b) {
printf("%d > %d \n", a, b);
}
上面的代码中对于a和b的比较,我们将其先转换为int类型的数据,然后对int类型的数据进行比较,那么就如同下面表示的那样:
a和b在比较的时候,需要转化为整型进行比较,而b又是无符号整型,所以在进行转换的时候a和b都化成了无符号整型
对于a,其是负数,在计算机中用补码存储,其原码为1000 0101
,所以其反码为1111 1010
,所以其补码为1111 1011
,所以如果将a转化为整型的时候,其会扩充为4个字节,会自动填充符号位,为
1111 1111 1111 1111 1111 1111 1111 1011
,最后将该数转换为无符号整型,即没有符号位
对于b,其是无符号char类型,在转换的时候自动填充0,也就是说其填充为:
0000 0000 0000 0000 0000 0000 0000 1010
由上面的分析可以明显看出,a在转换为无符号整型之后,其大小远远比b大,所以这里面是输出a>b
char ch = 'a';
int x = 0;
x = ch;
(int)ch = x;
char ch = 'a';
int x = 0;
x = ch;
x = (int)ch;
char a = 100;
char b = 200;
char c = a + b;
printf("%d %d \n", c, a + b);
unsigned char x = 100;
unsigned char y = 200;
unsigned char z = x + y;
printf("%d %d \n", z, x, y);
上面式子运行结果为
那么为什么会出现这种现象呢?
可以通过下图来找到结果:
char c = 128;
unsigned char uc = 128;
unsigned short us = 0;
us = c + uc;
printf("%x \n", us);
us = (unsigned char)c + uc;
printf("%x \n", us);
us = c + (char)uc;
printf("%x \n", us);
us = (unsigned short)c + uc;
printf("%x \n", us);
对于指针类型的转换,虽然指针都是四个字节,但是在其所指元素类型不一样的时候,需要对其进行强转,因为如果指针所指类型不一样,再转换的时候,内存默认给指针所指空间,分配原来所指类型大小,而加了强转之后,使得空间大小改变,如下面这段代码中指针的转换类似:
int a = 0x41440000;
int* ip = &a;
float* fp = (float*)&a;
printf("%x \n", *ip);
printf("%f \n", *fp);