【问题标题】:C warning(clang compiler) "integer literal is too large to be represented in a signed integer"C 警告(clang 编译器)“整数文字太大而无法用有符号整数表示”
【发布时间】:2020-02-20 23:46:04
【问题描述】:

我有这段代码

#include <stdio.h>

typedef signed long long v2signed_long 
      __attribute__ ((__vector_size__ (sizeof(signed long long) * 2)));

int main()
{
        v2signed_long v = {4611686018427387904LL, -9223372036854775808LL};

        printf("%lli, %lli\n", v[0], v[1]);
        return 0;
}

给出以下警告(相关问题没有帮助):

:7:45: warning: integer literal is too large to be represented in
       a signed integer type, interpreting as unsigned
  [-Wimplicitly-unsigned-literal]
    v2signed_long v = {4611686018427387904LL, -9223372036854775808LL};

有没有办法解决这个警告?谢谢!

【问题讨论】:

  • 没有真正检查我认为@Eljay 是正确的值。 (对我来说)令人惊讶的背景是 -1 不是整数文字,而是一个常量表达式,由整数文字 1 和一元减号运算符组成,正如人们所期望的那样,符号反转。现在,正整数文字9223372036854775808(稍后应用一元减号)对于 long long 值空间来说确实太大了,解决方案正是 Eljay 所说的:使用最大的正整数,反转它的符号,并减一。仍然是编译时表达式,所以没有坏处。
  • C 是一种邪恶的语言。 当然 -9223372036854775808LL 是一个正数,因此 - :) 或者您可以将其移植到 1 的补码计算机上,这也可以解决问题 :)
  • 又一个解决方案:(int64_t) -0x8000000000000000。当 C 变坏时,以同样的方式回应!

标签: c clang


【解决方案1】:

问题在于 -9223372036854775808LL 实际上不是整数文字。它是文字 9223372036854775808LL 并应用了一元 - 运算符。 9223372036854775808 的值太大,无法放入 signed long long,这就是您收到警告的原因。

您可以改用表达式-9223372036854775807LL - 1LL 来解决此问题。 9223372036854775807 的值与 -9223372036854775807LL 一样适合 signed long long,然后减去 1 即可得到所需的值。

或者,您可以使用宏LLONG_MIN

【讨论】:

  • 使用宏 LLONG_MIN 我认为这是的答案,可能应该是第一个。
【解决方案2】:

编译器会考虑这种构造

-9223372036854775808LL

就像一个整数文字 9223372036854775808LL 应用了一元运算符 - 。但是9223372036854775808 的值太大而无法存储在signed long long 类型的对象中。所以编译器会报错。

改为使用

#include <limits>

//...

v2signed_long v = 
{
    std::numeric_limits<long long>::max(), std::numeric_limits<long long>::min()
};

这是一个演示程序

#include <iostream>
#include <limits>
#include <vector>

int main() 
{
    std::vector<long long> v =
    {
        std::numeric_limits<long long>::max(), std::numeric_limits<long long>::min()
    };

    for ( const auto &item : v ) std::cout << item << '\n';

    return 0;
}

它的输出是

9223372036854775807
-9223372036854775808

当您删除 C++ 标记后,在 C 中代码可能看起来像

#include <stdio.h>
#include <limits.h>

int main(void) 
{
    long long int a[] = { LLONG_MAX, LLONG_MIN };

    printf( "%lld\n%lld\n", a[0], a[1] );

    return 0;
}

程序输出同上图。

在任何情况下,最好使用这种方法而不是幻数,因为这种方法只会让代码的读者感到困惑。

【讨论】:

    猜你喜欢
    • 2011-01-22
    • 2021-03-08
    • 2016-05-10
    • 1970-01-01
    • 2016-07-26
    • 1970-01-01
    • 2022-01-10
    • 2020-10-13
    • 2021-11-17
    相关资源
    最近更新 更多