使用char存int类型数字深究

在写代码的时候遇到一个位运算的bug,我将0的二进制00000000所有位都置为1后变成11111111,然后因为业务逻辑问题想对11111111做一个判断,判断语句为将一个字节的数字与11111111做比较,但是在匹配的时候我简单的将BYTE_NUM== 255进行匹配,发现了程序出现bug,最后进行gdb调试的时候发现是这个匹配出的问题,最后细想了解到255只是11111111的源码,而C语言都是按照补码进行存储而11111111的补码是-1,最后我也没有与-1进行匹配而是加了个位运算~(0 << 7)

对于有符号整数255的补码为什么是-1,首先我们将数字存与字节中,所以一个数字大小应该一个字节,但是一个字节可以表示的有符号数字是-128到127之间(因为第一位要做符号位),那么255怎么表示呢?我们简单的将255存入一个字节的空间中变成11111111,其中11111111是-1的补码

换句话说将一个数字存入一个char类型的字节中(正常一个数字是存入4个字节中)是存入的该数字补码到字节中,但是如果数字大于127小于255也就是大于一个字节可存入的最大正数就按照其源码存储,

#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{
    
    
    char a;
    a = 255;
    
    printf("255 store in char,and pirnt each bit of this char\n");
    
    for(int i = 0; i < 8; i++){
    
    
        printf("%d",!!((a << i) & 0x80));
        
    }
    printf("\n");
    
    
    
    a = -100;
    
    printf("-100 store in char,and pirnt each bit of this char\n");
    
    for(int i = 0; i < 8; i++){
    
    
        printf("%d",!!((a << i) & 0x80));
        
    }
    
    printf("\n");
    
    
    
    a = 100;
    
    printf("100 store in char,and pirnt each bit of this char\n");
    
    for(int i = 0; i < 8; i++){
    
    
        printf("%d",!!((a << i) & 0x80));
        
    }
    
    printf("\n");
    
    return 0;
}

输出如下,看到-100和100在一个字节内都是按照补码存储(100的源码是01100100,正数的源码和补码都一样),255是按照源码存储(因为没有地方存储符号位)

255 store in char,and pirnt each bit of this char
11111111
-100 store in char,and pirnt each bit of this char
10011100
100 store in char,and pirnt each bit of this char
01100100

我们再看存储257是啥样,因为257的二进制源码是0100000001,第一个bit(0)是符号位代表正数,如果存入一个字节(char)中百分之百会发生截取,但是我们不知道是截取前8bit(从左往右截取)还是截取后8bit(从右往左截取)

#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{
    
    
    char a;
    a = 257;
    
    printf("257 store in char,and pirnt each bit of this char\n");
    
    for(int i = 0; i < 8; i++){
    
    
        printf("%d",!!((a << i) & 0x80));
        
    }
    printf("\n");
	
	return 0;
}

输入如下,报了一个warning,告诉你将257存入一个字节中会发生overflow,但还是运行,最后发现编译器是从后往前截取

main.cpp: In function ‘int main()’:
main.cpp:9:9: warning: overflow in conversion from ‘int’ to ‘char’ changes value from ‘257’ to ‘'\001'’ [-Woverflow]
    9 |     a = 257;
      |         ^~~
257 store in char,and pirnt each bit of this char
00000001

总结
将一个数字存入一个char类型的字节中(正常一个数字是存入4个字节中)是存入的该数字补码到字节中,但是如果数字大于127小于255也就是大于一个字节可存入的最大正数就按照其补码存储,如果数字大于255那么会发生截取,比如将257存入一个字节的char中,先取257的补码(同源码)0100000001然后从后向前截取8bit,最后为0000001

猜你喜欢

转载自blog.csdn.net/qq_37026934/article/details/125760937
今日推荐