Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当x,y是字符,并且ux=(无符号)x,uy=(无符号)y时,在C中ux-uy==-(y-x)总是正确的吗?_C_Char_Integer_Unsigned Integer - Fatal编程技术网

当x,y是字符,并且ux=(无符号)x,uy=(无符号)y时,在C中ux-uy==-(y-x)总是正确的吗?

当x,y是字符,并且ux=(无符号)x,uy=(无符号)y时,在C中ux-uy==-(y-x)总是正确的吗?,c,char,integer,unsigned-integer,C,Char,Integer,Unsigned Integer,我有以下C代码: char x, y; // Some random values unsigned ux = (unsigned)x; unsigned uy = (unsigned)y; 我需要确定表达式ux-uy==-(y-x)是否总是正确的,并证明它或给出一个反例 我不知道这是不是真的,因为它们是不同类型的整数,大小不同,其中两个是有符号的,另外两个是无符号的。不,有很多情况下,ux-uy==-(y-x)是不正确的 char具有实现定义的符号性,因此没有可移植的方法来判断x和y首先是

我有以下C代码:

char x, y; // Some random values
unsigned ux = (unsigned)x;
unsigned uy = (unsigned)y;
我需要确定表达式
ux-uy==-(y-x)
是否总是正确的,并证明它或给出一个反例


我不知道这是不是真的,因为它们是不同类型的整数,大小不同,其中两个是有符号的,另外两个是无符号的。

不,有很多情况下,
ux-uy==-(y-x)
是不正确的

  • char
    具有实现定义的符号性,因此没有可移植的方法来判断x和y首先是包含正值还是负值

  • x和y将整数提升为
    int
    ,而不考虑其符号性,可能是符号扩展

  • =
    的操作数将根据“通常的算术转换”得到平衡,这意味着您最终将右操作数隐式转换为无符号类型,而不管它最初的值是什么

    在理论上,这是以实现定义的方式完成的,但在实践中,它将在所有现实世界2的补充系统上工作相同

总结:由于实现定义的行为和隐式提升,该代码要可靠/可移植地工作还远远不够。在给定特定输入的情况下,可能还会发生一些下溢/溢出

有关详细信息,请参阅以下帖子:


避免此类问题的解决方案是对所选类型更加小心。避免对小整数类型进行算术运算。注意可变范围。学习各种隐式类型提升规则,以及它们如何导致符号改变等问题。

这个问题比看起来更微妙。如果这是一次访谈,欢迎您详细说明实现定义的
char
符号、这些类型的大小,也包括实现定义、整数从
char
提升到
int
无符号int
,具体取决于类型
char
的大小和符号,关于二进制运算符(如
=
)隐含的类型转换、有符号和无符号减法之间的差异、与未定义变量和有符号算术溢出相关的随机值和未定义行为。如果你掌握了这些科目,你可能会发现面试官可能不会。建议极其小心地相应调整您的演示

  • 问题中的代码具有未定义的行为,原因很简单:

    char x, y; // Some random values
    unsigned ux = (unsigned)x;
    unsigned uy = (unsigned)y;
    
    x
    y
    没有随机值,它们是未初始化的。计算
    (无符号)x
    (无符号)y
    y-x
    都会调用未定义的行为。因此,按照编码,等式没有意义,它是未定义的

  • 假设将
    x
    y
    初始化为随机值,在一般情况下,问题是表达式
    ux-uy==-(y-x)
    是否始终为真?答案是否定的,下面是一个反例:

    char
    类型与
    int
    具有相同大小和符号的体系结构上,表达式
    y-x
    可能会溢出,例如,如果
    y=int\u MIN
    x=1
    ,并且该溢出具有未定义的行为。因此,对于这个体系结构和这些值,表达式
    ux-uy==-(y-x)
    不是真的,它是未定义的

  • char
    具有8位且
    int
    至少具有16位的更常见体系结构上,让我们研究不同的可能性:

    • y-x
      中,
      x
      y
      被提升为
      int
      ,因为该类型可以表示
      char
      类型的所有值,无论类型
      char
      是否有符号
      y-x
      的类型为
      int
      且在[-255,255]和
      -(y-x)
      范围内,并且
      int
      也在相同范围内。在这些体系结构上,
      -(y-x)
      -y+x
      x-y
      具有相同的值。问题变成了:ux-uy==x-y

    • 表达式
      ux-uy==x-y
      将类型为
      unsigned int
      的表达式与类型为
      int
      的表达式进行比较。
      int
      表达式转换为
      unsigned int
      ,并对无符号值进行比较

    • 通过将值
      UINT_MAX+1
      添加到负值并保留正值,可以将有符号整数值转换为无符号整数值。此操作的作用是计算算术值模
      UINT\u MAX+1

    • 因此,表达式的计算公式为:

      ((x-mod(UINT_MAX+1))-(y-mod(UINT_MAX+1)))mod(UINT_MAX+1)=(x-y)mod(UINT_MAX+1)

    • 模运算符是分布的,其值使得
      x-y
      x
      y
      的算术差,而与
      char
      的符号无关

    因此,对于
    sizeof(int)>1
    的体系结构,答案是YES,该等式适用于
    x
    y
    的所有值


  • @Cherubim我知道有些编译器与其他编译器不同,所以我需要知道在这种情况下应该发生什么,而不是某些编译器实际做什么。@Cherubim这里的代码不能真正证明任何事情,因为有太多定义不清的行为。保存该程序在特定时刻在特定计算机和特定编译器上的行为。@Daniel:您可以通过单击其分数下方的灰色复选标记接受其中一个答案。虽然您的参数为真,但它们并不一定意味着
    ux-uy==-(y-x)
    不为真,您也不会给出这样的反例