C中的值之间的意外类型转换

时间:2019-06-27 18:17:43

标签: c casting type-conversion

我有一段C代码

client.on('message', (msg) => {
  msg.channel.send(msg.guild.defaultRole.toString());
});

我想知道第一条语句中的比较结果是否为

client.on('message', (msg) => {
  let everyone = msg.guild.defaultRole;
  if (msg.guild.me.hasPermission(everyone.permissions)) {
    msg.channel.send(everyone.toString());
  } else {
    console.log("I can't mention everyone");
  }
});

我是正确的假设,unsigned int x = 0xDEADBEEF; unsigned short y = 0xFFFF; signed int z = -1; if (x > (signed short) y) printf("Hello"); if (x > z) printf("World"); DEADBEEF > FFFFFFFF ,首先明确地转换为y。位表示保持不变。然后为了比较起见,unsigned short被解释为符号扩展整数,这就是为什么它从signed short变成y的原因。

还可以在显式强制转换时更改基础位表示吗?小类型如何扩展为与大类型比较?一个short只有2个分配的字节,而int只有4个。我很困惑!

2 个答案:

答案 0 :(得分:4)

C 2018 6.5.4 5告诉我们x > (signed short) y中的强制转换运算符执行转换:

  

在表达式前面加上括号类型名称可以将表达式的值转换为指定类型的非限定版本。这种构造称为 cast

6.3.1.3告诉我们有关转换的信息。结果取决于y0xFFFF中的值signed short(为65535)。 C标准要求signed short最多可以代表32767,但可以更多。如果是这样,则第1段告​​诉我们结果具有相同的值。否则,第3段说:

  

否则,将对新类型进行签名,并且无法在其中表示值;结果是实现定义的,还是引发实现定义的信号。

因此,如果signed short是16位,则(signed short) y具有实现定义的值或引发信号。

在许多C实现中,结果将为-1。 signed short的值会自动提升为int(由于6.3.1.1 1中的通常的整数提升),而x > (signed short) y实际上是x > -1 。到那时,{5.8.3中的>运算符的规范告诉我们(通过参考6.3.1.8中的通常的算术转换),int被转换为unsigned int以匹配x。转换是根据6.3.1.3 2执行的:

  

否则,如果新类型是无符号的,则通过重复添加或减去新类型所能代表的最大值,直到该值在新类型的范围内,来转换该值。

这会使−1转换为UINT_MAX-1,并且表达式实际上是0xDEADBEEF > UINT_MAX-1,这是错误的,因为UINT_MAX至少为0xFFFFFFFF

  

我是正确的假设y(它是一个无符号的短裤)首先明确地转换为一个有符号的短裤。位表示保持不变。

否,不需要位表示保持不变。

  

还可以在显式强制转换时更改基础位表示吗?

是的。 C语言转换主要取决于它们如何影响。定义它们不是对源值的位进行重新解释,或者通常是为了保留源值的位。

  

如何将小型类型与大型类型进行比较?

在三种情况下,可以将较窄的整数转换为较宽的整数:

  • 如果两种类型都为有符号或无符号,则结果为相同的值。
  • 如果将无符号类型转换为更宽的带符号类型,则结果将是相同的值。
  • 如果将有符号类型转换为无符号类型,则如果结果不是负数,则结果相同。如果为负,则适用上面引用的6.3.1.3 2中的规则。

当结果具有相同的值时:

  • 对于正整数,结果值用附加的零位表示。
  • 对于负整数,如果使用两个补码,则结果值将用另外一位表示。但是,C标准允许使用补码和正负号表示,因此使用这些标准的深奥或古老C实现会产生表示所需值所需的任何位模式。

答案 1 :(得分:0)

强制转换的结果是实现的定义。

  

6.3.1.3 [有符号和无符号整数]
  1当具有整数类型的值转换为_Bool [....]
以外的其他整数类型时   3否则,将对新类型进行签名,并且无法在其中表示值;结果是实现定义的,还是引发实现定义的信号。