【问题标题】:What does 'u' mean after a number?数字后面的\'u\'是什么意思?
【发布时间】:2023-01-19 07:18:01
【问题描述】:

你能告诉我数字后面的 u 到底是什么意思吗,例如:

#define NAME_DEFINE 1u 

【问题讨论】:

    标签: c


    【解决方案1】:

    C 代码中的整数字面量(如 1)始终属于 int 类型。 intsigned int 相同。将 uU (等效)添加到文字以确保它是 unsigned int,以防止各种意外错误和奇怪的行为。

    这种错误的一个例子:

    在 int 为 16 位的 16 位机器上,此表达式将产生负值:

    long x = 30000 + 30000;
    

    这 30000 个字面量都是 int,并且由于两个操作数都是 int,所以结果将是 int。一个 16 位有符号整数只能包含最大 32767 的值,因此它会溢出。 x 因此会得到一个奇怪的负值,而不是预期的 60000。

    代码

    long x = 30000u + 30000u;
    

    但是会按预期运行。

    【讨论】:

    • this expression will result in a negative value。好吧,否则恶魔会飞出你的鼻子,因为整数溢出是未定义的行为。
    • @ouah 理论上是的。在现实世界中,我见过的所有编译器都以相同的方式处理整数溢出。反正不管结果如何都是bug。
    • 整数溢出未定义的事实不仅是理论上的。即使在现实世界中,编译器也会利用整数溢出作为未定义行为来执行优化。 gcc 例如至少有 20 种情况,它不考虑整数溢出来换行,因此它可以执行优化。一个简单的例子是像 a - 8 < 42 这样的表达式,如果 a 是有符号类型 gcc 可以将表达式简化为 a < 50
    • 回复@ouah 的评论:unsigned overflow定义,签名溢出不是。见:this SO question
    • @svec C 术语整数溢出未定义的行为,因为只有带符号的整数才能溢出。请参阅 C11,3.4.3p3“未定义行为的一个示例是整数溢出的行为”和 6.2.5p7“涉及无符号操作数的计算永远不会溢出,[...]”
    【解决方案2】:

    这是一种定义方式未签名文字整数常量。

    【讨论】:

      【解决方案3】:

      这是一种告诉编译器常量 1 用作无符号整数的方法。一些编译器假定任何没有像“u”这样的后缀的数字都是 int 类型的。为避免这种混淆,建议在将常量用作无符号整数时使用像“u”这样的后缀。其他类似的后缀也存在。例如,使用 float 'f'。

      【讨论】:

      • 不是“某些编译器”。所有编译器。
      • 我不想一概而论,因为我个人只使用过几个编译器。
      • 我的观点是,C 标准强制编译器将不带“u”的整数文字视为带符号的 int。
      • @Lundin 不完全正确,它也可以是 long 或 long long。如果没有后缀,整数文字的类型是intlonglong long中第一个可以保存值(如果有)的类型。
      • @DanielFischer:是的。但除非你写'u',否则它将始终是签名类型。
      【解决方案4】:

      它的意思是“unsigned int”,基本上它的功能类似于强制转换,以确保在编译时将数字常量转换为适当的类型。

      【讨论】:

      • 对,但是H2CO3说“它职能像演员”,他没有说一个演员!
      • 我的意思是,如果没有“u”,它将被签名,因为这是整数常量的默认值。所以 tge u 是通知编译器将其视为未签名。我知道这不是演员表,只是为了更好地理解的样本。
      【解决方案5】:

      代码中的十进制文字(八进制和十六进制文字的规则不同,请参阅https://en.cppreference.com/w/c/language/integer_constant)具有intlonglong long类型之一。从这些中,编译器必须选择足够大以容纳该值的最小类型。请注意,不考虑类型 charsigned charshort。例如:

      0 // this is a zero of type int
      32767 // type int
      32768 // could be int or long: On systems with 16 bit integers
            // the type will be long, because the value does not fit in an int there.
      

      如果给这样的数字添加一个u 后缀(大写的U 也可以),编译器将不得不从unsigned intunsigned longunsigned long long 中选择最小的类型。例如:

      0u // a zero of type unsigned int
      32768u // type unsigned int: always fits into an unsigned int
      100000u // unsigned int or unsigned long
      

      最后一个示例可用于显示与演员表的区别:

      100000u // always 100000, but may be unsigned int or unsigned long
      (unsigned int)100000 // always unsigned int, but not always 100000
                           // (e.g. if int has only 16 bit)
      

      旁注:在某些情况下,添加 u 后缀是确保计算正确性的正确做法,正如 Lundin 的回答所证明的那样。然而,也有严格禁止混合有符号和无符号类型的编码指南,即使是以下声明

      unsigned int x = 0;
      

      被归类为不合格,必须写成

      unsigned int x = 0u;
      

      这可能会导致这样一种情况,即经常处理无符号值的开发人员养成了在任何地方向文字添加 u 后缀的习惯。但是,请注意,更改签名会导致在各种情况下出现不同的行为,例如:

      (x > 0)
      

      可以(取决于 x 的类型)意味着不同于

      (x > 0u)
      

      幸运的是,编译器/代码检查器通常会就可疑情况向您发出警告。尽管如此,添加 u 后缀应该慎重考虑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-09-23
        • 1970-01-01
        • 2013-08-07
        • 2011-10-12
        • 2023-03-07
        • 2013-07-08
        • 1970-01-01
        相关资源
        最近更新 更多