相关疑难解决方法(0)

为什么带有GCC的x86上的整数溢出会导致无限循环?

以下代码进入GCC的无限循环:

#include <iostream>
using namespace std;

int main(){
    int i = 0x10000000;

    int c = 0;
    do{
        c++;
        i += i;
        cout << i << endl;
    }while (i > 0);

    cout << c << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以这是交易:有符号整数溢出在技术上是未定义的行为.但是x86上的GCC使用x86整数指令实现整数运算 - 它包含溢出.

因此,我本来期望它包装溢出 - 尽管事实上它是未定义的行为.但事实显然并非如此.那么我错过了什么?

我使用以下方法编译:

~/Desktop$ g++ main.cpp -O2
Run Code Online (Sandbox Code Playgroud)

GCC输出:

~/Desktop$ ./a.out
536870912
1073741824
-2147483648
0
0
0

... (infinite loop)
Run Code Online (Sandbox Code Playgroud)

禁用优化后,没有无限循环且输出正确.Visual Studio也正确编译它并给出以下结果:

正确的输出:

~/Desktop$ g++ main.cpp
~/Desktop$ ./a.out
536870912
1073741824
-2147483648
3
Run Code Online (Sandbox Code Playgroud)

以下是一些其他变体:

i *= 2;   //  Also …
Run Code Online (Sandbox Code Playgroud)

c c++ x86 gcc undefined-behavior

124
推荐指数
5
解决办法
1万
查看次数

什么属于教育工具,以展示人们在C/C++中做出的无根据的假设?

我想为SO准备一些教育工具,这应该有助于初学者(和中级)程序员识别和挑战他们在C,C++及其平台中的无根据的假设.

例子:

  • "整数环绕"
  • "每个人都有ASCII"
  • "我可以将函数指针存储在void*中"

我认为可以在各种平台上运行一个小型测试程序,它运行"合理的"假设,根据我们在SO中的经验,通常是由许多缺乏经验/半经验的主流开发人员制作的,并记录他们在各种机器上打破的方式.

这样做的目的不是要证明做某事是"安全的"(这是不可能做到的,测试只有在他们破坏的情况下证明了什么),而是向最难以理解的个体展示最不起眼的表达方式如果它具有未定义或实现定义的行为,则在另一台机器上中断..

为此,我想问你:

  • 如何改进这个想法?
  • 哪些测试会很好,它们应该是什么样的?
  • 您是否可以在可以获得的平台上运行测试并发布结果,以便最终得到平台数据库,它们之间的区别以及为什么允许这种差异?

这是测试玩具的当前版本:

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <stddef.h>
int count=0;
int total=0;
void expect(const char *info, const char *expr)
{
    printf("..%s\n   but '%s' is false.\n",info,expr);
    fflush(stdout);
    count++;
}
#define EXPECT(INFO,EXPR) if (total++,!(EXPR)) expect(INFO,#EXPR)

/* stack check..How can I do this better? */
ptrdiff_t check_grow(int k, int *p)
{
    if (p==0) p=&k;
    if (k==0) return &k-p;
    else return check_grow(k-1,p);
}
#define BITS_PER_INT (sizeof(int)*CHAR_BIT)

int bits_per_int=BITS_PER_INT;
int int_max=INT_MAX; …
Run Code Online (Sandbox Code Playgroud)

c c++ portability cross-platform

120
推荐指数
8
解决办法
8933
查看次数

编译器优化导致程序运行速度变慢

我在C中编写了以下代码.它非常简单,因为它恰好x为每个for循环进行了位移.

int main() {
   int x = 1;
   for (int i = 0; i > -2; i++) {
      x >> 2;
   }
}
Run Code Online (Sandbox Code Playgroud)

现在正在发生奇怪的是,当我刚刚编译它没有任何的优化或第一级优化(-O),它运行得很好(我定时可执行文件及其有关1.4s-O5.4s没有任何优化.

现在,当我添加-O2-O3切换编译并为生成的可执行文件计时时,它不会停止(我已经测试过60s).

关于可能导致这种情况的任何想法?

c gcc compiler-optimization

9
推荐指数
2
解决办法
1054
查看次数

printf(“%d \ n”,4294967296); 犯了一些奇怪的错误

(4294967296 = 2 ^ 32)

我想4294967296使用printf(“%u,%d”)进行打印,并想知道会发生什么,但是得到一些奇怪的结果。

代码如下:

printf("%d\n", 4294967296);

printf("d = %u = %d = 0x%x  \n", 4294967296, 4294967296, 4294967296);//this is strange

printf("d = %u = %d = 0x%x  \n", 4294967295 + 1, 4294967295 + 1, 4294967295 + 1);
Run Code Online (Sandbox Code Playgroud)

我的结果是

0

d = 0 = 1 = 0x0

d = 0 = 0 = 0x0
Run Code Online (Sandbox Code Playgroud)

结果图

您可以在第二行中看到4294967296的二进制表达式是0x0,但是当我打印4294967296使用“%d”时,它将显示1,这让我感到困惑。我期望1的输出为0。

c visual-studio-2017

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

负数是打印

我是C编程新手并试图理解数据类型.

我指定了以下变量:

  int nsamples = 10000000;
  int n = 32;
  int m = 64;


  int nrpoinnts = n*m*nsamples+99;
  printf("Nr points %d\n",nrpoinnts);
Run Code Online (Sandbox Code Playgroud)

由于某种原因,打印的数字是负数.为什么会这样?我很难超过nrpoinnts的价值范围,所以我检查了双倍.最终的结果是我也得到了负值.

c

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