【问题标题】:How does explicit casting work in C? [duplicate]显式转换如何在 C 中工作? [复制]
【发布时间】:2015-12-28 04:40:18
【问题描述】:

假设我有以下代码行:

int a; // 4-byte-integer
char b, c, d, e;

b = (char)(a >> 24);
c = (char)(a >> 16);
d = (char)(a >> 8);
e = (char)a;

我们还假设系统以 little-endian 模式和a = 100 存储字节。

当使用这样的显式转换时,最左边的字节会消失吗? 我猜想在执行上述几行之后,变量将保存这些值:b=100, c=0, d=0, e=0。对吗?

【问题讨论】:

  • 除非您使用unsigned 变量,否则这将导致undefined behaviour。然后最重要的部分将被截断。字节顺序在此示例中无关紧要。
  • @WeatherVane 是未定义行为还是意外行为?符号位的行为是确定性的。
  • @nicomp 只要行为是意料之外的,为什么不应该是未定义的?
  • 右移负符号整数是实现定义,而不是未定义行为。标准说(§6.5.7):E1 >> E2 的结果是E1 右移E2 位位置。如果E1 具有无符号类型或E1 具有带符号类型和非负值,则结果的值是E1 / 2 ** E2 商的整数部分。如果E1 具有带符号类型和负值,则结果值是实现定义的。(我使用2 ** E2 表示2 的E2 次方,因为2<sup>E2</sup> 在cmets 中不起作用,甚至在代码引号之外(2E2 — 看!)。

标签: c casting explicit


【解决方案1】:

你猜对了!但你的解释并不完全正确:

  • 上述代码的行为不依赖于系统的字节序:如果int是32位,char是8位,a >> 24是高位字节,a & 255是低位顺序字节,用于所有可能的字节顺序。

  • 不需要显式转换为(char),因为C 会将表达式值隐式转换为赋值目标的类型。我想程序员这样写是为了消除编译器警告。众所周知,Microsoft 编译器在分配丢失精度方面直言不讳。

  • 最左边的字节不会消失,该值是以char的大小为模计算的,在你的情况下希望是8位,所以(char)aa & 255 基本相同。但是如果char 被签名,如果值超过CHAR_MAX,标准实际上并没有很好地定义这种行为。使用unsigned 类型进行这种位操作是明智的。

【讨论】:

    猜你喜欢
    • 2013-04-04
    • 2012-02-29
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多