int如何转换为char以及char如何转换为int?

时间:2016-11-08 05:05:27

标签: c type-conversion implicit-conversion

在下面的示例中,打印了包含全1的字节的位表示:

#include <stdio.h>
int main (void)
{
  char c = 255;
  char z;
  for (int i = 7; i >= 0; i--) {
    z = 1 << i;
    if ((z & c) == z) printf("1"); else printf("0");
  }
  printf("\n");
  return 0;
}

输出为11111111

现在我们将char c更改为int c,以便示例变为:

#include <stdio.h>
int main (void)
{
  int c = 255;
  char z;
  for (int i = 7; i >= 0; i--) {
    z = 1 << i;
    if ((z & c) == z) printf("1"); else printf("0");
  }
  printf("\n");
  return 0;
}

现在输出为01111111

为什么输出不同?

更新

编译以下test.c

#include <stdio.h>
int main(void)
{
  char c=-1;
  printf("%c",c);
  return 0;
}

$ gcc test.c
$ ./a.out | od -b
0000000 377
0000001

输出为377,这意味着glibc与gcc相矛盾,因为signed char会自动转换为unsigned char。 为什么这样的并发默认情况下使char无符号是合理的。有什么具体原因没有?

3 个答案:

答案 0 :(得分:1)

  • 这里的第一个问题是char类型。永远不应该使用此类型来存储整数值,因为它具有实现定义的签名。这意味着它可以是有符号或无符号的,并且您将在不同的编译器上获得不同的结果。如果给定编译器上char未签名,则此代码将按预期运行。

    但是如果char已签名,则char c = 255;会产生一个太大的值。然后,值255将以某种特定于编译器的方式转换为带符号的数字。通常通过将原始数据值转换为二进制补码等价物。

    像GCC这样的好编译器会给出一个警告:“隐式常量转换溢出”。

    从不使用char来存储整数来解决这个问题。请改用uint8_t

  • 当您尝试将1 << 7存储在给定编译器上签名的char类型中时,会出现同样的问题。当发生这种情况时,z将以负值(-128)结束。

  • 在表达式z & c中,两个操作数都以静默方式整数提升为类型int。每当您使用小整数类型(例如char)时,大多数C表达式都会发生这种情况。

    &运算符不关心操作数是否有符号,它将对变量的“原始数据”值执行按位AND运算。如果c是已签名的char并且原始值为0xFF,那么您将获得一个结果为负数,并设置符号位。在两台补充计算机上的值-1

所以回答为什么你在两种情况下得到不同的结果:

当您将类型切换为int时,值255将适合c,而不会转换为负值。 &操作的结果也将是int,此int的符号位将永远不会设置,与char情况下的情况不同。

执行-128 & 255时,结果将为128(0x80)。这是一个正整数。 z是一个负整数,其值为-128。它将被==运算符提升为int,但符号会被保留。由于128不等于-128,因此MSB将打印为零。

如果您将char切换为uint8_t,则会得到相同的结果。

答案 1 :(得分:0)

编辑澄清&#34;默认签名&#34;

在第一个列表中,(z == c)测试两个 char ;但是,在第二个列表中,(z == c)测试一个 char 和一个 int

为了在 char int 之间执行&==操作,编译器会扩展 char int 的大小。

关于第7位(第8位):

如果您的编译器默认情况下将 char 视为无符号,则条件为

(((int)(128) & (int)255) == (int)128)

将呈现 true ,并打印1。但是在您的情况下,结果为false,并显示0

原因很可能是你的编译器认为 char 是签名的(默认情况下是gcc)。在这种情况下,设置为1 << 7 char 实际上是-128,而在 int (至少两个字节)中,255是正数。< / p>

(char)-128扩展为int (int)-128,因此条件

if ((z & c) == z) 

读取

if (((int)(-128) & (int)255) == (int)-128)

在这种情况下是假的。

答案 2 :(得分:0)

对于char到int,你必须将char定义为unsigned,因为默认情况下char或任何类型都被视为singed。

 int main (void)
 {
 int c = 255;
 unsigned char z;
 int i;
 for (i = 7; i >= 0; i--) {
 z = 1 << i;
 if ((z & c) == z) printf("1"); else printf("0");
 }
 printf("\n");
 return 0;
 }