【问题标题】:Does c standard guarantee bit pattern interpretation for signed and unsigned?c标准是否保证有符号和无符号的位模式解释?
【发布时间】:2011-12-16 13:06:37
【问题描述】:

C 标准是否规定应如何解释位表示?换句话说,如果条件总是评估为真,请执行以下操作?假设 sizeof (int) = 4 和 CHAR_BIT = 8

unsigned u = 0xffffffff;
if (u == 4294967295) /* do something */

int i = 0xffffffff;
if (i == -1) /* do something */

unsigned u = (int)0xffffffff;
if (u == 0xffffffff) /* do something */

int i = hex_literal;
unsigned u;
memcpy (&u, &i, sizeof (u));
if (i == u) /* do something */
if ((i & 0x7fffffff) == (u & 0x7fffffff)) /* do something */

int i = hex_literal;
unsigned u = i;
if (i == u) /* do something */

unsigned u = hex_literal;
int i = u;
if (i == u) /* do something */

int i = hex_literal;
unsigned u = hex_literal;
if (i == hex_literal && u == hex_literal) /* do something */

char c = 0xff;
if (c >> 4 == 0xf) /* do something */

signed char c = 0xff;
if (((c >> 4) & 0xff) == 0xf) /* do something */

【问题讨论】:

    标签: c bit standards signed representation


    【解决方案1】:

    我将做一个额外的假设,即在讨论的实现中没有类型具有填充位。让我们一次拿一个:

    unsigned u = 0xffffffff;
    if (u == 4294967295) /* do something */
    

    是的。

    int i = 0xffffffff;
    if (i == -1) /* do something */
    

    没有。将超出范围的数字转换为有符号类型会产生实现定义的结果。

    unsigned u = (int)0xffffffff;
    if (u == 0xffffffff) /* do something */
    

    不,和前面的例子一样。

    int i = hex_literal;
    unsigned u;
    memcpy (&u, &i, sizeof (u));
    if (i == u) /* do something */
    if ((i & 0x7fffffff) == (u & 0x7fffffff)) /* do something */
    

    是的。该标准保证有符号类型中的每个值位在对应的无符号类型的对象表示中具有相同的值。

    int i = hex_literal;
    unsigned u = i;
    if (i == u) /* do something */
    

    是的。将iint 提升到unsigned 是确定性的,并且在分配给u 和比较时都会产生相同的值。

    unsigned u = hex_literal;
    int i = u;
    if (i == u) /* do something */
    

    是的,但前提是hex_literalint 可表示的(正)值范围内 - 否则实现定义的结果会再次出现。

    int i = hex_literal;
    unsigned u = hex_literal;
    if (i == hex_literal && u == hex_literal) /* do something */
    

    u == hex_literal 将始终计算为 true,但 i == hex_literal 仅在 hex_literalint 可表示的值范围内时才需要这样做。

    char c = 0xff;
    if (c >> 4 == 0xf) /* do something */
    

    char 可以签名或未签名。如果它是无符号的,那么测试将是真的;如果已签名,则 cc >> 4 将具有实现定义的值,因此可能不正确。

    signed char c = 0xff;
    if (((c >> 4) & 0xff) == 0xf) /* do something */
    

    c 将具有实现定义的值,因此测试可能不正确。

    请注意,除了memcpy() 之外,您的所有问题都只与有关,而不是表示

    【讨论】:

      【解决方案2】:

      对于未签名的,是的。对于有符号类型,否;该标准允许 2 的补码、1 的补码或符号幅度表示。标准(C99)的相关部分是6.2.6.2。

      另一个问题是 unsigned u = (int)0xffffffff 之类的代码会调用未定义的行为,因为这会导致整数溢出(第 6.3.1.3 节)。

      还有一个问题是 char c = 0xff; c >> 4 这样的代码是实现定义的,原因有两个。首先,char 可以是signedunsigned。其次,如果是signed,则右移负数是实现定义的(第 6.5.7 节)。

      【讨论】:

        【解决方案3】:

        要记住的关键项目是十六进制文字(例如0x0F)指的是(这里:15),而不是物理存储位和字节的顺序。

        这取决于机器如何存储 - 有些将首先存储最低有效位,其他先存储高位,而 x86 上的 AFAIK 它是最低有效位 byte 首先但高 位 首先。

        但总是正确的,0x000F 等于 15

        【讨论】:

        • 在 bits 的上下文中定义“first”!
        • 让我们说位 #0 (2^0) - 但我现在不确定,因为这在过去太久了。我只是想指出,并非所有架构都使用相同的顺序。
        • G 没有意义 2^0 最不重要的一个 :-)
        • 我的意思是,位的顺序只有在您发送它们时才有意义,例如串行总线。如果他们只是坐在记忆中,没有“第一”和“最后”。
        【解决方案4】:

        无符号数保证模 2^n 算术。签名的没有这样的保证。

        没有提到位模式。请注意,0xfffffff 不是“位模式”,它是一个数字(其“位模式”对 C++ 标准没有意义),如果x 是一个 32 位无符号数,则保证满足 x + 1 = 0你分配了 0xffffffff。

        【讨论】:

        • 它被定义为由位组成,并且按位运算符是根据这些位定义的(好吧,除了左移是用数字定义的)。因此,唯一值得怀疑的是它是否是一个“模式”——如果是,那么它就是一个位模式。
        猜你喜欢
        • 2016-04-24
        • 1970-01-01
        • 2010-09-14
        • 2020-05-01
        • 2011-11-14
        • 1970-01-01
        • 1970-01-01
        • 2022-01-22
        • 1970-01-01
        相关资源
        最近更新 更多