我刚刚回答了这个问题,它问为什么迭代直到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++的答案,如果有的话.
我有一个使用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) 我知道这是一个简单的问题,但我很困惑.我有一个相当典型的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)
我已经特别为常量加了后缀,为什么会发生这种情况呢?
阅读大师Stanley Lippman的"C++入门",我才知道,在默认情况下十进制整数是有符号的(最小的类型int,long或long long在其字面的价值符合),而八进制和十六进制文字可有符号或无符号的(最小的类型int,unsigned int,long,unsigned long,long long或unsigned 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无符号十六进制常数,十六进制长整型ç字面解释为"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.有什么问题?
我正在阅读一些代码,并在枚举的最后一个值中找到了_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) 我正在努力改进我的嵌入式编码实践.下面的代码将值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)
我有两个问题:
为了使用MemoryWrite我必须转换0x80001000为的宏2147487744.我认为这使得代码不清楚.有没有办法只使用十六进制值才能做到这一点?
我定义reset_value为uint32_t.如果我使用它会改变什么#define?