002

002.C语言进制、ASCII码和基础数据类型

数字进制表示法

在日常生活中,我们计数往往使用十进制。然而在计算机中,由于计算机只能用高低电平呈现不同状态,所以使用0-1二进制来表示数字:低电平表示“0”,高电平表示“1”。

二进制转十进制

我们分别计算每一位权重,再分别相加即可,例如:

101 = 1 * 22 + 0 * 21 + 1 * 20 = 5

十进制转二进制

对于十进制转换二进制,数学上的方法是不断地除以2,但这样稍显麻烦,我们也可以像下面这样进行转化:

首先我们要记住一些常见的数字:

20 1

21 2

22 4

23 8

24 16

25 32

26 64

27 128

28 256

29 512

210 1024

然后我们以“1000”为例,进行转换。我们要做的,其实就是从1~1024这十个数中找出可以组成1000的数字,从最大的512开始组合,显然1000 = 512 + 256 + 128 + 64 + 32 + 8,所以二进制为0011 1110 1000,通过这种方法,我们可以口算得出二进制表示。

为什么会有八进制和十六进制呢?

按理来说,十进制和二进制,对于人类与计算机沟通已经足够了,那么为什么人们还要发明八进制和十六进制呢?

在上面1000的例子中,我们发现它的二进制表示有12位,对于更大的数字,长度可能会更加夸张,所以人们想要在存储二进制信息的同时更加节约空间。我们可以发现,对于3位二进制,正好是0-7,对于4位二进制,正好是0-15,于是通过八进制和十六进制,我们可以用一位空间存储二进制中三位甚至四位的信息,大大的节约了空间。

image-20251002105500569

在C语言中表示进制

我们以一段c语言代码来演示:

#include <stdio.h>

int main() {
	char a1 = 12;//十进制
    char a2 = 012;//八进制
    char a3 = 0x12;//十六进制
	printf("a1 = %d\n", a1);
    printf("a2 = %d\n", a2);
    printf("a3 = %d\n", a3);
    printf("a3 = %d, %o, %x\n", a3, a3, a3);
	
	return 0;
}

这里我们着重解释最后一个printf,首先0x12在十进制中代表1 * 161 + 2 = 18,八进制中则有18 = 2 * 81 + 2,所以用22表示,十六进制就是12本身,结果为a3 = 18, 22, 12

ASCII码表

img

img

下面演示一下用十进制、八进制、十六进制和字符形式表示'9':

#include <stdio.h>

int main(){
	char a1 = '9';
    char b1 = '\12';
	printf("a1 = %d, %o, %x, %c\n", a1, a1, a1, a1);
    printf("b1 = %d, %o, %x\n", b1, b1, b1);
	
	return 0;
}

代码运行结果为:

a1 = 57, 71, 39, 9
b1 = 10, 12, a

这里的 \n 代表换行,这样的符号还有很多:

\r:回车

\t:用tab键控制占位符

\数字:数字的表示字符(默认八进制)

基础数据类型

不同数据的存储空间

我们在认识基础数据类型之前,需要先了解存储单位:

在硬件中,单位为bit

在软件中,单位为B(1B = 8bit)

对于不同的数据类型,其需要的存储空间也不相同:

数据类型 存储空间大小
char 1B(最小单位)
int <= 4B
long >= 4B
short 2B
float 4B
double 8B

在一些古老的编译器中,认定int为2字节,但是在如今64位系统中,往往都是4B,int的具体大小要视编译器而定

下面用一段代码来表示不同数据类型的存储空间大小

#include <stdio.h>

int main(){
    int a;
    printyf("size: int = %d\n", sizeof(a));
    printyf("size: short = %d, long = %d\n", sizeof(short), sizeof(long));
    
    return 0;
}

long赋值的一些隐患

long a = 10099456;

上面的这个赋值语句,我们感觉好像是对的,因为int一般是4字节,10099456现在在这个范围内。但是当我们在一些比较老的机器上运行这段代码时,由于老机器上int可能为2字节,所以程序会报错,我们推荐像下面这样写,以规避一致性问题上的错误:

long a = 10099456L;

加了一个'L',代表10099456为long类型,至少都有4个字节。

类似的,还有float = 1.1f;

原码与补码

在二进制中,我们会遇到需要负数计算的情况,此时就需要用到补码

对于'-1':

原码:1000 0001

反码:1111 1110

补码:1111 1111(原码保留符号位,剩余取反再加一)

使用补码,我们在使用二进制进行负数计算时,就可以规避双0问题

当我们需要进行数学计算时,一般都使用(signed) int,gcc上默认但是MSVC不默认,为了一致性,我们可以统一写signed int。

然而,当我们只需要进行数据储存时,我们推荐使用unsigned int,这样可以让我们表示更多的数据。

posted on 2025-10-04 14:16  Khalilll  阅读(3)  评论(0)    收藏  举报