我有以下功能:
char f1( int a, unsigned b ) { return abs(a) <= b; }
Run Code Online (Sandbox Code Playgroud)
对于执行速度,我想重写如下:
char f2( int a, unsigned b ) { return (unsigned)(a+b) <= 2*b; } // redundant cast
Run Code Online (Sandbox Code Playgroud)
或者使用此签名,即使对于非负面也可能具有微妙含义b:
char f3( int a, int b ) { return (unsigned)(a+b) <= 2*b; }
Run Code Online (Sandbox Code Playgroud)
这两种替代方案都可以在一个平台上进行简单的测试,但我需要便携式.假设非负b且没有溢出风险,这是典型硬件和C编译器的有效优化吗?它对C++也有效吗?
注意:作为C++在gcc 4.8 x86_64上使用-O3,f1()使用6个机器指令并f2()使用4.指令f3()与那些相同f2().同样感兴趣的是:如果b以文字形式给出,则两个函数都编译为3条指令,这些指令直接映射到指定的操作f2().
当我运行这个时:
int main() {
unsigned a = 5;
std::cout << -a << std::endl;
int b = -a;
std::cout << b << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我明白了:
4294967291
-5
Run Code Online (Sandbox Code Playgroud)
看起来它有效,我可以取 an 的负数unsigned并将其分配给 an int,但这真的总是可以吗?为什么?
当我尝试一些对我来说看起来类似的情况时:
int c = 1;
int d = 3;
double x = c/d;
std::cout << x << std::endl;
Run Code Online (Sandbox Code Playgroud)
我明白了0(正如预期的那样)。
PS:也许有一个骗局,但我没有找到它,我能找到的最接近的是这个
试图在我的C++程序中添加异常处理,但我觉得它很混乱.程序将值i和j设置为它们的最高可能值并递增它们.我想我希望异常处理在发生时检测整数溢出/环绕(?)
到目前为止,这就是我所拥有的:
#include <iostream>
#include <limits.h>
#include <exception>
#include <stdexcept>
using namespace std;
int main() {
int i;
unsigned int j;
try{
i = INT_MAX;
i++;
cout<<i;
}
catch( const std::exception& e){
cout<<"Exception Error!";
}
try{
j = UINT_MAX;
j++;
cout<<j;
}
catch(const std::exception& e){
cout<<"Exception Error!";
}
}
Run Code Online (Sandbox Code Playgroud)
程序运行,但异常处理部分不起作用.
可能是什么问题?
如何将ulong转换为long,结果与我在c ++中得到的结果相同.
C++
unsigned long ul = 3633091313;
long l = (long)ul;
l is -661875983
Run Code Online (Sandbox Code Playgroud)
C#
ulong ul = 3633091313;
long l = (long)ul;
l is 3633091313
Run Code Online (Sandbox Code Playgroud) 我有一个遗留的代码库,我们正试图从中迁移devtoolset-4到devtoolset-7.我注意到有关有符号整数溢出的有趣行为(int64_t具体而言).
有一个代码片段,用于检测整数溢出,同时乘以一大组整数:
// a and b are int64_t
int64_t product = a * b;
if (b != 0 && product / b != a) {
// Overflow
}
Run Code Online (Sandbox Code Playgroud)
这段代码与devtoolset-4一起工作正常.但是,使用devtoolset-7时,永远不会检测到溢出.
例如:当a = 83802282034166和b = 98765432,
product变为-5819501405344925872(显然值已溢出).
但product / b结果价值等于a (83802282034166).因此,if情况永远不会成真.它的值应该根据overflown(负)product值计算:-5819501405344925872 / 98765432 = -58922451788
具有讽刺意味的是,数学是正确的,但它导致devtoolset-4的异常行为.
product / b != a
为product != a * b并达到相同的溢出值(或者可能只是根据上面的语句跳过计算 …我有一个函数,它接受一个字符串作为输入,然后按以下方式将加权值的乘积分配给变量:字母表中的每个字母对应于2到101之间的素数,以及每个字符的值.输入字符串相乘并存储在int变量中,如下所示:
int result=1;
/* some other code */
result*=letterweight[index];
Run Code Online (Sandbox Code Playgroud)
有足够长的字符串会导致溢出.那么,我的问题如下:
在给定结果的情况下,如何确定可能的正确值?
例如:if result == 1066849907,是否会产生其他值,忽略intC中的值范围?
我无法控制原始代码,无法确定是否发生溢出.我只想找出一系列可能的结果,无论这个数字有多大.
在以下代码中:
#include<cstdio>
#define max(a,b) (a>b?a:b)
using namespace std;
int main()
{
int f=10000000;
long long i=(long long)max(1000000,f*f);
printf("%lld",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到了输出
276447232
但如果我写
long long i=max((long long)1000000,(long long)f*f);
Run Code Online (Sandbox Code Playgroud)
我得到了输出
百兆
这两条线有什么区别?为什么在第一种情况下不会发生类型转换?
我试图打印Ascii字符,我发现使用char c = NUM; printf("%c", c);将适用于某些数字(尝试使用Ascii数字的某些字母表)但有些会导致运行时错误,为什么会这样?
#include <stdio.h>
int main(void) {
for(int i = 0; i < 128; i++){
printf("%c", i); // WORKS FINE
}
for(char c = '!'; c < '~'; c++){
printf("%c", c); //WORKS FINE
}
#if 0
for(char d = 0; d < 128; d++){
printf("%c", d); //IF REMOVED #if 0 --> RUNTIME ERROR
}
#endif
// HOWEVER
char e = 105;
printf("%c", e); //OK
return 0;
}
Run Code Online (Sandbox Code Playgroud)
那么,为什么最后一部分工作而第三部分for循环不是?
在看到下面的答案之后,我明白我的循环已经病态了,我应该在127而不是128停止它.但是,当我尝试这个改变时 - 它根本没有输出:
for(unsigned char …Run Code Online (Sandbox Code Playgroud) 如果intA*intB结果足够大,则会在2 ^ 31边界溢出,并且您无法获得预期的结果.
int64_t value = (intA * intB) - int64A
然而,这产生了预期值.
int value = (intA * intB) - int64A
在低级别发生了什么意味着存储在int中的相同(坏)操作是正确的,但是在int64_t中却没有?
在 Arduino Uno 上运行的这段代码会打印递增的数字,并按预期从 32767 回绕到 -32768。
int16_t i = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
i++;
Serial.println(i);
}
Run Code Online (Sandbox Code Playgroud)
然而,人们认为在功能上等效的这段代码不断打印超过 200000 个 16 位数字(有符号或无符号)应该能够表示的数字。
void setup() {
Serial.begin(115200);
int16_t i = 0;
while(true) {
i++;
Serial.println(i);
}
}
void loop() {}
Run Code Online (Sandbox Code Playgroud)
Arduino 参考中有关于数据类型的注释/警告int。这有关系吗?
当有符号变量超过其最大或最小容量时,它们就会溢出。溢出的结果是不可预测的,因此应该避免这种情况。溢出的典型症状是变量从最大容量“滚动”到最小容量,反之亦然,但情况并非总是如此。如果您想要这种行为,请使用 unsigned int。
第二个代码片段发生了什么?变量如何明显代表这么大的数字而不滚动?
c++ ×9
c ×3
algorithm ×2
arduino ×1
ascii ×1
c# ×1
char ×1
devtoolset ×1
long-integer ×1
native ×1
syntax ×1
types ×1
ulong ×1
unsigned ×1
visual-c++ ×1