C语言学习(long和char强制类型转换)

C语言学习(long和char强制类型转换)

在不同的计算机架构中,数据的存储方式可能不同。大端(Big-endian)和小端(Little-endian)是两种常见的字节序。在大端系统中,数据的高位字节存储在内存的低地址端,在小端系统中,数据的低位字节存储在内存的低地址端。由于long类型通常占用4字节(32位,linux64下占用八字节,不影响本文通用性),而char类型占用1字节(8位),在强制转换时,只有long的最低8位会被转换为char。这意味着除了最低8位之外的其他位将被丢弃。如果long类型的值是负数,那么在转换为char时,符号位会被扩展。在大多数情况下,这会导致char类型的值变成一个负数,但由于char类型通常以无符号数处理,所以这个负数会被解释为一个正数。

示例如何将long类型转换为char类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main() {
long l = 0x12345678L; // 一个示例的long值
char c;

// 强制类型转换,只取l的最低8位
c = (char)l;

// 打印结果
printf("The long value: 0x%lX\n", l); // long十六进制输出
printf("The char value: 0x%X\n",
c); // 格式化char打印x,在 ASCII 编码中,字符 x 的十进制值是
// 120,十六进制值是 0x78,在小端系统中的最低字节就是0x78
printf("The char(char) value: %c\n",
c); // 强转后的char格式化输出,即十六进制数0x78的ASCII编码
printf("The char(int) value: %d\n",
c); // 因为 128 超出了 char 类型的最大值 127。在这种情况下,128
// 会被解释为 -128
return 0;
}

输出:

1
2
3
4
The long value: 0x12345678
The char value: 0x78
The char(char) value: x
The char(int) value: 120

在这个例子中,long类型的值0x12345678L只有最低8位0x78被转换为char类型。如果long是负数,那么转换的结果将取决于编译器如何处理符号扩展。这种转换可能会导致数据丢失,因此在实际编程中,如果需要处理大量的数据,应该使用足够大的数据类型来避免丢失重要的信息

十六进制数通常用来表示无符号整数。然而,如果你想要表示一个负数,你需要使用一个有符号的整数类型,比如intlong。在C语言中,负数通常使用二进制补码形式来表示。在十六进制中表示负数时,你通常会看到一种表示方法,即在十六进制数前加上负号(-)来表示它是负数。但是,这并不是一个真正的十六进制表示,因为十六进制数本身并不包含符号信息。符号是由变量的类型和上下文决定的。

例如,如果你有一个int类型的变量,并且你想要给它赋一个十六进制表示的负数值,你可以这样做:

1
2
3
4
5
6
7
#include <stdio.h>

int main() {
int num = -0x1A3F; // 表示一个负数
printf("The value of num in decimal: %d\n", num);
return 0;
}

在这个例子中,-0x1A3F是一个负数,它的值是-0x1A3F的二进制补码表示。printf函数会根据int类型来解释这个值,并打印出它的十进制表示。负数在ASCII编码中没有对应的字符,所以在转换成char类型时会显示乱码。
如果你想要在十六进制中表示一个负数的二进制补码形式,你需要知道这个数的位宽。例如,如果int是32位宽,那么-0x1A3F的二进制补码表示可能是0xFFFFFFFFFFFFE5C1(这个值取决于0x1A3F的二进制表示和整数的位宽)。
在实际编程中,通常不需要手动计算二进制补码形式,因为编译器会自动为你处理这些细节。你只需要使用负号和十六进制数来表示负数即可。

long类型的变量l被初始化为 128,其二进制表示是 10000000。当这个值被强制转换为 char 类型时,由于 char 是有符号的,并且只能表示 -128127 的范围,所以 128 的二进制表示 10000000 被解释为 -128,-128 的二进制表示被符号扩展到 long 类型,结果为 4294967168(十六进制0xFFFFFF80char 类型中 128 的二进制补码表示,符号扩展的意思是,最高位(符号位)的值会被复制到新类型中所有高位上)。

1
printf("The char(long) value: %ld\n", c); // 输出4294967168

反之,因为 0xFFFFFF80 二进制的最高位是 1,所以它表示一个负数。当我们将这个 char 值转换为 long 类型时,符号位(即 1)会被复制到 long 类型的所有高位上,直到填满整个 long 类型的位宽。

1
printf("The char(long) value: %ld\n", (long)c); // 强制类型转换了变量c,输出-128