整数转字符类型的转换

10
int i = 259;       /* 03010000 in Little Endian ; 00000103 in Big Endian */
char c = (char)i;  /* returns 03 in both Little and Big Endian?? */
在我的电脑上,c 字符被分配了 03,并且我使用的是小端序(Little Endian),但我不知道字符转换是否读取最不重要的字节或读取由 i 变量指向的字节。
4个回答

14

在这里,字节序并不会对任何事情产生影响。它并不尝试存储其中一个字节(MSB、LSB等)。

  • 如果char是无符号的,它将会发生包装。假设8位char,则259%256 = 3。
  • 如果char是有符号的,那么结果是实现定义的。感谢pmg:C99标准6.3.1.3/3

3
如果char是有符号的,行为是实现定义的(参见C99标准中的6.3.1.3/3)。此外,char是有符号还是无符号也是实现定义的。 - pmg
@pmg,谢谢您提供的章节编号 :-) - cnicutar
2
由于它是实现定义的,因此实现当然可以自由地使用最高有效字节甚至饱和... :-) 但在现实世界中,它们都像无符号一样执行相同的操作,即将值减少模数目的可表示目标类型。 - R.. GitHub STOP HELPING ICE

7

由于您正在从较大的整数类型转换为较小的整数类型,因此它将获取最不重要的部分,而不考虑字节序。但是,如果您转换指针,则会获取地址处的字节,这取决于字节序。

因此,c = (char)i 将最不重要的字节赋给 c,但是 c = *((char *)(&i)) 会将地址为 i 的第一个字节赋给 c,在小端系统上是相同的。


2

如果您想测试小/大端,请使用联合(union):

int isBigEndian (void)
{
    union foo {
        size_t i;
        char cp[sizeof(size_t)];
    } u;

    u.i = 1;
    return *u.cp != 1;
}

它之所以起作用,是因为在小端模式下,它看起来像01 00 ... 00,而在大端模式下,它将是00 ... 00 01(省略号由零组成)。 因此,如果第一个字节为0,则测试返回true。否则返回false。 然而,请注意,也存在存储数据方式不同的混合字节序计算机(有些可以切换字节序;其他只是以不同的方式存储数据)。 PDP-11将32位int存储为两个16位字,除了字的顺序被颠倒(例如0x01234567为4567 0123)。

0

当从int(4字节)转换为char(1字节)时,它将保留最后1个字节。例如:

int x = 0x3F1;         // 0x3F1 = 0000 0011 1111 0001
char y = (char)x;      // 1111 0001  --> -15 in decimal (with Two's complement)
char z = (unsigned char)x;    // 1111 0001 --> 241 in decimal

无符号字符 z = (无符号字符)x; - user3094631

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接