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 |
|
输出:
1 | The long value: 0x12345678 |
在这个例子中,long
类型的值0x12345678L
只有最低8位0x78
被转换为char
类型。如果long
是负数,那么转换的结果将取决于编译器如何处理符号扩展。这种转换可能会导致数据丢失,因此在实际编程中,如果需要处理大量的数据,应该使用足够大的数据类型来避免丢失重要的信息。
十六进制数通常用来表示无符号整数。然而,如果你想要表示一个负数,你需要使用一个有符号的整数类型,比如int
或long
。在C语言中,负数通常使用二进制补码形式来表示。在十六进制中表示负数时,你通常会看到一种表示方法,即在十六进制数前加上负号(-)来表示它是负数。但是,这并不是一个真正的十六进制表示,因为十六进制数本身并不包含符号信息。符号是由变量的类型和上下文决定的。
例如,如果你有一个int
类型的变量,并且你想要给它赋一个十六进制表示的负数值,你可以这样做:
1 |
|
在这个例子中,-0x1A3F
是一个负数,它的值是-0x1A3F
的二进制补码表示。printf
函数会根据int
类型来解释这个值,并打印出它的十进制表示。负数在ASCII编码中没有对应的字符,所以在转换成char类型时会显示乱码。
如果你想要在十六进制中表示一个负数的二进制补码形式,你需要知道这个数的位宽。例如,如果int
是32位宽,那么-0x1A3F
的二进制补码表示可能是0xFFFFFFFFFFFFE5C1
(这个值取决于0x1A3F
的二进制表示和整数的位宽)。
在实际编程中,通常不需要手动计算二进制补码形式,因为编译器会自动为你处理这些细节。你只需要使用负号和十六进制数来表示负数即可。
long类型的变量l
被初始化为 128
,其二进制表示是 10000000
。当这个值被强制转换为 char
类型时,由于 char
是有符号的,并且只能表示 -128
到 127
的范围,所以 128
的二进制表示 10000000
被解释为 -128
,-128 的二进制表示被符号扩展到 long 类型,结果为 4294967168(十六进制0xFFFFFF80
即char
类型中 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 |