char,signed char,unsigned char以及原码反码补码

前言

我们首先来看一个代码,可以便于理解后面的内容

#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
    char a = -1;
    signed char b = -1;//有符号位
    unsigned char c = -1;//无符号位

    printf("%d %d %d\n", a, b, c);

    return 0;
}

规定了三个char类型,但存放的却是整形数据-1;

最后使用库函数printf打印这三个整形数据;

对于以往的经验来说我们只用char类型存放字符,这里为什么可以存放整形呢。

我们常常用int来规定一个整型变量,一个整型大小是四个字节,而一个字符型大小是一个字节。那为什么int就可以规定一个数字,而char就不可以呢? 答案是可以的;用char存放的字符,实际上也是用ASCLL码(A-Z,a-z的ASCLL码值分别是65-90和97-122;)表示的。最后用%c打印就可以展现出来。如下图

char,signed char,unsigned char以及原码反码补码_第1张图片

我们看到即便规定了一个整型变量a,里面存放的是97,但最后只要打印的时候使用%c打印

字符数据,就可以打印出a;同理,char a=-1当然也可以使用%d打印;

下图为最上面代码的输出结果

char,signed char,unsigned char以及原码反码补码_第2张图片

我们可以看到红色方框标出的结果。前面两个-1没啥说的,但最后的255是怎么回事呢?

为什么(unsigned char c = -1)最后打印出来是255呢?明明给c赋值为-1;

引入

我们可以知道,数字在计算机中其实是用二进制码存放的,并且使用的是补码;

-1的原码,反码,补码分别为:

原码:10000000 00000000 00000000 00000001

反码:11111111 11111111 11111111 11111110

补码:11111111 11111111 11111111 11111111

原码反码补码都占据32个比特位,也就是四个字节,刚好是一个整型数据的大小,这也就是我们为什么经常用int规定一个整型数据的原因。

解释:char—字符型;

signed char—有符号字符型;

unsigned char—无符号字符型;

字符型不用说,那么有无符号字符型是什么意思呢?对于-1的二进制码来说,char和signed char都指的是二进制码的首位代表数据的正负(1负0正);而unsigned char则指的是没有符号位,即不分正负。

一个char数据类型大小是一个字节,而一个整型数据却是四个字节,那么问题来了。怎么存放的下呢?

确实是存放不下,但我们能存多少存多少啊是吧。所以char类型实际上只能存放二进制码(补码)低位(后面)的8比特,即11111111,这块用术语叫截断。

那么问题又来了,我们用的是%d打印数据啊。这只有一个字节(8比特)怎么打印?

好办!给前面补,补够32位。char,和signed char 都是截断之后的8比特数据首位是1就补1,0就补0;unsigned char则是给前面全部补0;这就是整型提升

结论

发生整型提升之后的原码,反码,补码:

  1. char,signed char

补码:11111111 11111111 11111111 11111111

反码:11111111 11111111 11111111 11111110

原码:10000000 00000000 00000000 00000001

所以最后打印出来是-1;

  1. unsigned char

补码:00000000 00000000 00000000 11111111

反码:00000000 00000000 00000000 11111111

原码:00000000 00000000 00000000 11111111

整型提升以后unsigned char变成正数了,正数的原反补码都相同;我们读一下这个unsigned char的原码是不是255;

char,signed char,unsigned char以及原码反码补码_第3张图片

结束!

你可能感兴趣的:(C语言,c++,c语言,开发语言)