相关疑难解决方法(0)

整数文字的类型默认不是int?

我刚刚回答了这个问题,它问为什么迭代直到for循环中的100亿需要更长时间(OP实际上在10分钟后中止)比迭代直到10亿:

for (i = 0; i < 10000000000; i++)
Run Code Online (Sandbox Code Playgroud)

现在我和其他许多人明显的答案是,这是因为迭代变量是32位(从未达到100亿)并且循环得到无限循环.

但是虽然我意识到了这个问题,但我仍然想知道编译器内部究竟发生了什么?

由于文字没有附加一个L,它应该是IMHO类型int,因此32位.因此,由于溢出,它应该是int范围内的正常可达.为了真正认识到无法从中获取int,编译器需要知道它是100亿,因此将其视为超过32位的常量.

这样的文字是否会自动升级到拟合(或至少是实现定义的)范围(在这种情况下至少是64位),即使没有附加L并且是这个标准行为?或者是在幕后发生了什么不同,比如UB由于溢出(整数溢出实际上是UB)?标准中的一些引用可能很好,如果有的话.

虽然最初的问题是C,但我也很欣赏C++的答案,如果有的话.

c c++ overflow literals

32
推荐指数
2
解决办法
1万
查看次数

-gsign-compare警告用g ++表示

我有一个使用64位整数比较的代码.它看起来类似于以下内容:

#include <cstdio>

long long getResult()
{
    return 123456LL;
}

int main()
{
    long long result = getResult();

    if (result > 0x000FFFFFFFFFFFFFLL
        || result < 0xFFF0000000000000LL)
    {
        printf("Something is wrong.\n");

        if (result > 0x000FFFFFFFFFFFFFLL
            || result < -4503599627370496LL)
        {
            printf("Additional check failed too.\n");
        }
        else
        {
            printf("Additional check went fine.\n");
        }
    }
    else
    {
        printf("Everything is fine.\n");
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当这个代码用g ++编译(在Ubuntu 12.04 x64上尝试不同的版本:4.6.3,4.6.4,4.7.3,4.8.0)时带有标志-Wall -pedantic -std = c ++ 0x test.cpp -o测试我得到第一个if语句的第二行的-Wsign-compare警告(从g ++ - 4.8输出):

test.cpp:13:17: warning: comparison between …
Run Code Online (Sandbox Code Playgroud)

c++ g++ c++11

9
推荐指数
1
解决办法
2297
查看次数

即使L后缀,C中的十六进制常量也是无符号的

我知道这是一个简单的问题,但我很困惑.我有一个相当典型的gcc警告,通常很容易修复:
warning: comparison between signed and unsigned integer expressions

每当我有一个带有最高有效位的十六进制常量时,如0x80000000L,编译器会将其解释为无符号.例如,使用-Wextra编译此代码将导致警告(gcc 4.4x,4.5x):

int main()
{
long test = 1;
long *p = &test;
if(*p != 0x80000000L) printf("test");
}
Run Code Online (Sandbox Code Playgroud)

我已经特别为常量加了后缀,为什么会发生这种情况呢?

c comparison gcc compile-time-constant gcc-warning

8
推荐指数
1
解决办法
4782
查看次数

为什么十进制和十六进制整数文字处理方式不同?

阅读大师Stanley Lippman的"C++入门",我才知道,在默认情况下十进制整数是有符号的(最小的类型int,longlong long在其字面的价值符合),而八进制和十六进制文字可有符号或无符号的(最小的类型int,unsigned int,long,unsigned long,long longunsigned long long文字的价值适合).

以不同方式处理这些文字的原因是什么?

编辑:我正在尝试提供一些上下文

int main()
{
    auto dec = 4294967295;
    auto hex = 0xFFFFFFFF;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在Visual Studio中调试以下代码显示decis unsigned long的类型和类型hexis unsigned int.
这与我读过的内容相矛盾但仍然存在:两个变量代表相同的值,但属于不同的类型.那令我困惑.

c++

6
推荐指数
1
解决办法
358
查看次数

- Hex Literal的-Wsign-conversion警告

我最近遇到了以下问题.因为它有点棘手,所以我把它作为未来人们的问答对.

根据这些问题(用C无符号十六进制常数,十六进制长整型ç字面解释为"L")文字被装配到能够代表他们的第一个数据类型.在这种情况下,列表应该是:

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
Run Code Online (Sandbox Code Playgroud)

此行为来自C标准6.4.4.1.但是,如果您编写以下代码(我使用C++)并-Wsign-conversion启用:

int32_t mask = 0xFF00FF00;
Run Code Online (Sandbox Code Playgroud)

...然后得到:

<file>:<line>:17: warning: conversion of unsigned constant value to negative integer [-Wsign-conversion]
  int32_t mask = 0xFF00FF00;
                 ^
Run Code Online (Sandbox Code Playgroud)

我发现这很奇怪,因为它0xFF00FF00是整数的二进制表示-16,711,936,很容易适合int.有什么问题?

c c++ literals

3
推荐指数
1
解决办法
192
查看次数

枚举的最后一个_BIG_ENUM = 0xFFFFFFFF是什么意思?

我正在阅读一些代码,并在枚举的最后一个值中找到了_BIG_ENUM = 0xFFFFFFFF。这行的正确含义是什么。并且此_BIG_ENUM在代码中的任何地方都没有使用。

#define CLS_COMM_CONFIG PORT_0,BAUD_9600,DATA_BIT_8,ONE_STOP,NO_FLOW_CONTROL
#define PLS_COMM_CONFIG PORT_1,BAUD_115200,DATA_BIT_8,ONE_STOP,NO_FLOW_CONTROL

typedef enum _comm_config
{

 _Zero=0,
 PORT_0=_Zero,
 BAUD_2400=_Zero,
 NONE=_Zero,
 HALF_STOP=_Zero,
 DATA_BIT_5=_Zero,
 NO_FLOW_CONTROL=_Zero,

 _One = 1,
 PORT_1=_One,
 BAUD_4800=_One,
 ODD=_One,
 ONE_STOP=_One,
 DATA_BIT_6=_One,

 _Two=2,
 PORT_2=_Two,
 BAUD_9600=_Two,
 EVEN=_Two,
 TWO_STOP=_Two,
 DATA_BIT_7=_Two,

 _Three=3,
 PORT_3=_Three,
 BAUD_19200=_Three,
 DATA_BIT_8=_Three,

 _Four=5,
 PORT_5=_Four,
 BAUD_115200=_Four,
 DATA_BIT_9=_Four,

 _BIG_ENUM=0xFFFFFFFF,

}COMMConfig;
Run Code Online (Sandbox Code Playgroud)

c enums

2
推荐指数
1
解决办法
66
查看次数

c使用#define和十六进制值代替十进制的良好编程习惯

我正在努力改进我的嵌入式编码实践.下面的代码将值0写入内存位置0x80001000.

#define MemoryWrite(A,V) *(volatile unsigned long*)(A)=(V)
#define FLAG 2147487744 //0x80001000

uint32_t reset_value = 0;

int main(void)
{
    MemoryWrite(FLAG, reset_value);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

  1. 为了使用MemoryWrite我必须转换0x80001000为的宏2147487744.我认为这使得代码不清楚.有没有办法只使用十六进制值才能做到这一点?

  2. 我定义reset_valueuint32_t.如果我使用它会改变什么#define

c embedded hex

1
推荐指数
1
解决办法
974
查看次数