【问题标题】:Arithmetic operation on int32 and int64 with parentheses带括号的 int32 和 int64 的算术运算
【发布时间】:2016-02-26 16:33:03
【问题描述】:

给定这个操作:

int64_t a_int64, b_int64 = WHATEVER1;
int32_t c_int32 = WHATEVER2;

a_int64 = b_int64 - (c_int32 * 1000000);

c_int32 是否在乘法前提升为 int64_t?我知道所有整数在任何算术运算之前都被提升到至少“int”大小,如果二元运算符的等级高于 int,则提升到更大操作数的大小。但是括号内的运算是否与(第二个)运算,即减法分开处理?

【问题讨论】:

  • 确定 - 只需使用 1000000ULL 表示乘法的两个参数都应提升为至少 64 位
  • 注意:() 是括号。括号是[]
  • @Lashane:正确的是使用INT64_C 宏。而OP使用有符号整数,后缀U是错误的。
  • @Ian:如果溢出,这是未定义的行为。您不能测试未定义的行为。
  • @Lashane __STDC_CONSTANT_MACROS 是在哪里定义的?我不熟悉这个宏。

标签: c integer-arithmetic


【解决方案1】:

但是括号内的运算是否与(第二个)运算,即减法分开处理?

是的;评估c_int32 * 1000000 所涉及的促销活动不以任何方式依赖于上下文。之后,由于该上下文而导致的任何必要转换都会发生在结果上。

也就是说,c_int32 * 1000000 仅在不溢出的情况下才被明确定义;在这种情况下,64 位提升发生在乘法之前还是之后都没有关系。因此,编译器可以以任何一种方式合法地执行此操作(例如,如果它看到一些优化机会)。

【讨论】:

    【解决方案2】:

    From another good SO post on the topic:

    C99,§6.4.4.1

    整数常量的类型是第一个 可以表示其值的对应列表。

    表 6

    int
    long int
    long long int
    

    因此,c_int32 的自动提升将取决于整数文字的大小。在这种情况下,在 32 位系统上,您的整数文字将很容易放入 in32_t 变量中。

    这不是进行整数运算的好方法。使您的代码尽可能明确,不要有任何机会。

    a_int64 = b_int64 - ((int64_t)c_int32 * 1000000LL);
    

    【讨论】:

    • 这个答案没有错,但不是回答OP的问题,而是在谈论其他事情的过程中预设了正确的答案。 OP提出了一个具体、合理的问题;如果没有别的,任何答案都应该回答它。
    • @ruakh 我认为以上回答了 OP 的问题。它“取决于”文字本身的值。我注意到在 32 位系统上,它将适合 32 位 int。更明确地说,文字将评估为int,并且对于c_int32 的大多数可能值,将发生溢出。这个问题得到了解决,但可能不像观众要求的那样明确。
    • C 标准是 C11,而不是 C99。答案应该从标准中引用。最终草案 n1570 可免费获得。而要提供 64 位 int(或可能的最小类型),INT64_C 宏是更好的选择。
    • @Olaf,同意将乘法扩大到int64_tINT64_C(int64_t) 就足够了。使用LL 可以工作,但可能会不必要地推动宽度,我认为这是你的观点,比如在long long 是128 位的未来系统上。 (我遇到了类似的问题here
    • @chux:是的,就是这个想法。在一个定义的目标上并且没有考虑到可移植性(例如一个嵌入式系统),我实际上对后缀很好 - 主要是因为我也是一个懒惰的编码器:-),但是 SO 答案应该看得更远并且使用最多正确的代码。
    猜你喜欢
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 2021-10-22
    • 2014-03-20
    • 1970-01-01
    • 2014-10-16
    相关资源
    最近更新 更多