-2147483648是具有32位的整数类型的最小整数,但它似乎会在if(...)句子中溢出:
if (-2147483648 > 0)
std::cout << "true";
else
std::cout << "false";
Run Code Online (Sandbox Code Playgroud)
这将true在我的测试中打印出来.但是,如果我们将-2147483648转换为整数,结果将是不同的:
if (int(-2147483648) > 0)
std::cout << "true";
else
std::cout << "false";
Run Code Online (Sandbox Code Playgroud)
这将打印false.
我糊涂了.谁能对此作出解释?
更新02-05-2012:
感谢您的评论,在我的编译器中,int的大小是4个字节.我正在使用VC进行一些简单的测试.我在我的问题中改变了描述.
这篇文章中有很多非常好的回复,AndreyT对编译器在这样的输入上的行为以及如何实现这个最小整数给出了非常详细的解释.另一方面,qPCR4vir给出了一些相关的"好奇心"以及如何表示整数.太棒了!
对于学校项目,我要编写C函数printf.事情进展顺利,但有一个问题我找不到合适的答案,所以我在这里.
printf("PRINTF(d) \t: %d\n", -2147483648);
Run Code Online (Sandbox Code Playgroud)
告诉我(gcc -Werror -Wextra -Wall):
error: format specifies type 'int' but the argument has type 'long'
[-Werror,-Wformat]
printf("PRINTF(d) \t: %d\n", -2147483648);
~~ ^~~~~~~~~~~
%ld
Run Code Online (Sandbox Code Playgroud)
但是如果我使用int变量,一切都很顺利:
int i;
i = -2147483648;
printf("%d", i);
Run Code Online (Sandbox Code Playgroud)
为什么?
我理解了许多观点,他们非常有趣.无论如何,我猜printf是使用<stdarg.h>librairy,所以,va_arg(va_list ap, type)也应该返回正确的类型.对于%d和%i,显然返回的类型是int.它有什么改变吗?
考虑以下程序.
#include <stdio.h>
int negative(int A) {
return (A & 0x80000000) != 0;
}
int divide(int A, int B) {
printf("A = %d\n", A);
printf("negative(A) = %d\n", negative(A));
if (negative(A)) {
A = ~A + 1;
printf("A = %d\n", A);
printf("negative(A) = %d\n", negative(A));
}
if (A < B) return 0;
return 1;
}
int main(){
divide(-2147483648, -1);
}
Run Code Online (Sandbox Code Playgroud)
在没有编译器优化的情况下编译它时,它会产生预期的结果.
gcc -Wall -Werror -g -o TestNegative TestNegative.c
./TestNegative
A = -2147483648
negative(A) = 1
A = -2147483648
negative(A) = 1 …Run Code Online (Sandbox Code Playgroud) 当我遇到一些我觉得奇怪的行为时,我正在研究一个嵌入式项目.我设法在键盘上重现它(见下文)以确认,但我的机器上没有任何其他C编译器可以在它们上进行尝试.
场景:我有一个#define32位整数可以容纳的最负值,然后我尝试使用它来与浮点值进行比较,如下所示:
#define INT32_MIN (-2147483648L)
void main()
{
float myNumber = 0.0f;
if(myNumber > INT32_MIN)
{
printf("Everything is OK");
}
else
{
printf("The universe is broken!!");
}
}
Run Code Online (Sandbox Code Playgroud)
键盘链接:http://codepad.org/cBneMZL5
对我来说,看起来这个代码应该可以正常工作,但令我惊讶的是它打印出来The universe is broken!!.
此代码隐式地将其转换INT32_MIN为a float,但事实证明,这会导致浮点值为2147483648.0(正!),即使浮点类型完全能够表示-2147483648.0.
有没有人对这种行为的原因有任何见解?
代码解决方案:正如Steve Jessop在他的回答中提到的,limits.h并且已经stdint.h包含正确的(工作)int范围define,所以我现在使用这些而不是我自己的#define
问题/解决方案解释摘要:鉴于答案和讨论,我认为这是对正在发生的事情的一个很好的总结(注意:仍然阅读答案/评论,因为它们提供了更详细的解释):
longS,SO大于任何值LONG_MAX且小于或等于ULONG_MAX随后L后缀的类型为unsigned long(-2147483648L)实际上是-一个unsigned …我的片段:
auto i = -2147483648;
int j = 3;
std::swap(i, j); // Compile error about mismatched types here.
Run Code Online (Sandbox Code Playgroud)
编译器声明文字i是a long long.这是为什么?-2147483648适用于intMSVC x64.
我的编译器是MSVC,目标是64位.
在Visual Studio 2010上的以下程序
#include <iostream>
using std::cout;
int main()
{
cout << -2147483646 << '\n';
cout << -2147483647 << '\n';
cout << -2147483648 << '\n'; // numeric_limits<int>::min()
cout << -2147483649 << '\n';
cout << -2147483650 << '\n';
cout << "..." << '\n';
cout << -4294967293 << '\n';
cout << -4294967294 << '\n';
cout << -4294967295 << '\n'; // -numeric_limits<unsigned int>::max()
cout << -4294967296 << '\n';
cout << -4294967297 << '\n';
}
Run Code Online (Sandbox Code Playgroud)
生成以下输出
-2147483646
-2147483647
2147483648
2147483647
2147483646
...
3
2 …Run Code Online (Sandbox Code Playgroud) 当我在使用GCC of MinGW编译的Windows7 x64下运行以下代码时,结果似乎是下溢的:
cout<<-2147483648 ; //Output: 2147483648
Run Code Online (Sandbox Code Playgroud)
但是当我将它分配给整数变量时,或者只是简单地将其转换为int类型:
cout<<(int)-2147483648 ; //Output: -2147483648
Run Code Online (Sandbox Code Playgroud)
那么,我的代码的先前版本出了什么问题?我不是int类型吗?或整数的下界究竟是什么?非常感谢.
为什么1不大于-0x80000000.我知道它与溢出有关.但有人可以解释为什么吗?是0x80000000不是常数我认为是吗?
assert(1 > -0x80000000);
Run Code Online (Sandbox Code Playgroud)
断言在C++中触发.这是为什么?
我很感激所提供的一些答案.但是C++标准是否定义了常量需要存储在32位整数中?为什么编译器没有认识到80000000不适合32位整数并且使用64位呢?我的意思是,最大的32位int可以是0x7FFFFFFF.0x80000000明显大于那个.为什么编译器仍然使用32位呢?
由于 C++20 二进制补码表示是标准允许的唯一表示,保证范围从 -2 N-1到 +2 N-1 -1。因此,对于 64 位有符号整数类型,范围从-9'223'372'036'854'775'808到9'223'372'036'854'775'807。但是,此代码不能在 Visual Studio 上编译(也不能在 gcc 上编译)
int main()
{
long long x{-9'223'372'036'854'775'808LL};
// error C4146: unary minus operator applied to unsigned type, result still unsigned
// error C2397: conversion from 'unsigned __int64' to '__int64' requires a narrowing conversion
}
Run Code Online (Sandbox Code Playgroud)
然而,如果我用long long x{-9'223'372'036'854'775'807LL - 1}compiles替换代码就好了并x保持正确的值。我没有得到什么?
#define SCALE (1 << 31)
#define fix_Q31_80(x) ( (int) ( (float)(x)*(float)0x80000000 ) )
#define fix_Q31_SC(x) ( (int) ( (float)(x)*(float)SCALE ) )
int main()
{
int fix_80 = fix_Q31_80(0.5f);
int fix_sc = fix_Q31_SC(0.5f);
}
Run Code Online (Sandbox Code Playgroud)
为什么价值观fix_80和fix_sc不同?
fix_80 == Hex:0x40000000
fix_sc == Hex:0xc0000000
Run Code Online (Sandbox Code Playgroud) 要提取无符号32位整数的高位字和低位字,并将每个字存储在单独的uint16_t变量中,我执行如下操作(nbr是无符号的32位整数):
uint16_t lower_word = (uint16_t) nbr & 0x0000FFFF; // mask desired word
uint16_t upper_word = (uint16_t) ((nbr & 0xFFFF0000) >> 16); // right-shift after masking
Run Code Online (Sandbox Code Playgroud)
显式转换为uint16_t是不必要的吗?还有什么其他更有效的方法,如果有的话,你建议获得所需的结果而不是这种方法吗?
我正在努力改进我的嵌入式编码实践.下面的代码将值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?
我的代码中有预定义的十六进制值。以下是其中之一。
#define ADDRESS1 0xD445556BD557
#define ADDRESS2 0xED612BDF113B
Run Code Online (Sandbox Code Playgroud)
我也有一个uint8_t数组。喜欢
uint8_t MAC[6];
Run Code Online (Sandbox Code Playgroud)
如何在不编写新函数的情况下比较这两件事?
我已经尝试过
if(MAC == ADDRESS2)
Run Code Online (Sandbox Code Playgroud)