【问题标题】:How is the conversion being done in this C code?在这个 C 代码中是如何进行转换的?
【发布时间】:2017-03-07 03:53:23
【问题描述】:
#include<stdio.h>
#include<string.h>

void printlength(char *s, char *t) {
    unsigned int c=0;
    int len = ((strlen(s) - strlen(t)) > c) ? strlen(s) : strlen(t);
    printf("%d\n", len);
}

void main() {
    char *x = "abc";
    char *y = "defgh";
    printlength(x,y);
}

当我编译它时,它给出了 3,但是,我不明白这里的转换是如何发生的:(strlen(s) - strlen(t)) > c )

【问题讨论】:

  • 这是非常糟糕的代码 (strlen(s) - strlen(t))总是 >= 0,因为它是无符号数学。
  • 所以优化器可以翻译成printf("%d\n", (int)strlen(s) );
  • @M.M 除非字符串长度相同,否则printf("%d\n", (int)strlen(t) );
  • @chux 如果它们的长度相同,那么strlen(t) 可以替换为strlen(s)
  • @M.M 是的!在这一点上,您的优化编译器大脑超过了我的。

标签: c string unsigned


【解决方案1】:

这是非常糟糕的代码(strlen(s) - strlen(t)) 总是 >= 0,因为它是无符号数学。 strlen() 返回的类型是size_t,一些无符号类型。因此,除非值相等,否则由于无符号数学回绕,差值始终为正数。

然后int len = strlen(s); 即使s 的长度与t 不同。

使用类似代码的更好方法是只添加。

// ((strlen(s) - strlen(t)) > c) 
(strlen(s) > (c + strlen(t)) 

注意:在带有 SIZE_MAX &lt;= INT_MAX 的罕见平台上,差异可能是负数,因为数学是使用 signed 类型 int 完成的。然而,与c 的比较是unsigned,然后发生在unsigned 导致负差异被“环绕”到一个非常大的数字,大于0。@Paul Hankin

【讨论】:

  • 总是?如果 SIZE_MAX
  • @PaulHankin 没有区别,因为通过与unsigned int变量的比较,负减结果仍然被提升为无符号
  • @PaulHankin 减法中使用的类型不受c 类型的影响,因此差异始终>= 0。结果比较将应用于更广泛的size_t 和@ 987654337@。虽然没有具体说明,但从未遇到过unsignedsize_t 更宽的平台——也许某些 64 位图形处理器可能会采用您的前提。
  • 在@PaulHankin 前提SIZE_MAX &lt;= INT_MAX 的基础上,减法 经历整数转换int 数学。然而,比较会发生在 unsigned math 上,并且结果相同。
  • @Barry 没有类型转换(例如(int))根据整数提升有类型转换。比较&gt; 采用左侧(size_t 或很少int)和右侧(unsigned)的类型并将一侧提升到另一侧的更高排名,这肯定是size_tunsigned。在任何情况下,比较都是通过一些无符号数学来完成的。
猜你喜欢
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-14
  • 2010-12-13
  • 2013-07-24
相关资源
最近更新 更多