【问题标题】:Shouldn't C++ compiler issue a warning for literal to negative number conversionsC++ 编译器不应该对文字到负数的转换发出警告吗
【发布时间】:2016-08-20 09:10:13
【问题描述】:

我在下面的代码中犯了一个非常愚蠢的错误:

int main(int argc, char *argv[])
{
    const int ARR_SIZE = 2147483648;
    int* intarr = (int *) malloc(sizeof(int) * ARR_SIZE);
    for(int i =0; i < ARR_SIZE; i++) {
        intarr[i] = i;
    }
}

所以我真的应该为 ARR_SIZE 使用无符号整数。 2147483648 分配给带符号的 32 位 int 时实际上是最大的负数。 编译器不(或不应该)为此发出警告是否有充分的理由。在分配大于类型最大值的正文字时,我是否应该要求显式转换? (对于我真的想要一个负数的情况)

(当我遇到这个问题时,源语言是 C++,但我认为这也是一个 C 问题)。

这是用 g++ 6.1.1 编译的:

g++ -Wall -g -o test_so test_so.cpp

【问题讨论】:

  • int的大小主要是平台相关的。
  • 问题是缺少编译器版本和编译选项。
  • 关于“正面文字”:没有“负面文字”。
  • "所以我真的应该使用 unsigned int" 是的,即size_t。它就是为此而生的。

标签: c++


【解决方案1】:

使用开关-Wconversiongcc,您将在 ILP32、LP64、LLP64 平台上收到以下警告:

test.c:5:26: error: conversion to ‘int’ alters ‘long int’ constant value
                    [-Werror=conversion]
    const int ARR_SIZE = 2147483648;

此警告标志包含在-Wall-Wextra 中。


还要注意,整数文字总是有一个足够大的类型来包含它,但至少在 C 上是 int。(在 C++ 上,字符文字将具有 char 类型!)。在这种情况下,2147483648 的类型为 long int,因为在此平台上,long int 具有 64 位 (LP64);在 Windows (LLP64) 上,它将是一个 `long long int'。

引用圣书(n1570),

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

对于无后缀的十进制文字,列表为 intlong intlong long int

【讨论】:

  • 感谢 Antii。很好的答案。我注意到,当我使用文字 0x10000000 代替时,即使使用 -Wconversion,我也不再收到此警告。这是有道理的,因为正如您所说,将负数表示为十六进制文字是很常见的。
  • @Avatar33 现在这是溢出,它被-Wall 捕获。你的意思可能是0x80000000。这被-Wconversion-Wsign-conversion 捕获,因为十六进制常量是无符号的。
  • 0x10000000(7 个尾随零)不是溢出,但我的意思不是 0x80000000 是的。
  • ahh :D 我把它读成 8 个零,是的,这会单独给 -Wall 一个警告。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多