相关疑难解决方法(0)

还有理由在C++代码中使用`int`吗?

许多样式指南(例如Google建议使用int索引数组时作为默认整数使用).随着64位平台的兴起,大多数时候a int只有32位,这不是平台的自然宽度.因此,除了简单的说法,我认为没有理由保持这种选择.我们清楚地看到编译以下代码的位置:

double get(const double* p, int k) {
  return p[k];
}
Run Code Online (Sandbox Code Playgroud)

被编译成

movslq %esi, %rsi
vmovsd (%rdi,%rsi,8), %xmm0
ret
Run Code Online (Sandbox Code Playgroud)

其中第一条指令将32位整数提升为64位整数.

如果代码转换成

double get(const double* p, std::ptrdiff_t k) {
  return p[k];
}
Run Code Online (Sandbox Code Playgroud)

生成的程序集现在

vmovsd (%rdi,%rsi,8), %xmm0
ret
Run Code Online (Sandbox Code Playgroud)

这清楚地表明,CPU感觉更在家std::ptrdiff_t比使用int.许多C++用户已经迁移到了std::size_t,但我不想使用无符号整数,除非我真的需要模数2^n行为.

在大多数情况下,使用int不会损害性能,因为未定义的行为或有符号整数溢出允许编译器在内部将任何内容int提升为std::ptrdiff_t处理索引的in循环,但我们从上面清楚地看到编译器不会感到宾至如归int.此外,std::ptrdiff_t在64位平台上使用会使溢出不太可能发生,因为当我们看到越来越多的人被int溢出困住时,他们必须处理大于2^31 - 1现在变得非常普遍的整数.

从我所看到的,这使得唯一int脱颖而出似乎是文字,如事实5int,但我不认为它会引起任何问题,如果我们移动到std::ptrdiff_t一个默认的整数.

我即将成为std::ptrdiff_t我小公司编写的所有代码的事实上的标准整数.这有什么理由可能是一个糟糕的选择吗?

PS:我同意这个名字 …

c++

181
推荐指数
7
解决办法
2万
查看次数

为什么这个循环产生"警告:迭代3u调用未定义的行为"并输出超过4行?

编译:

#include <iostream>

int main()
{
    for (int i = 0; i < 4; ++i)
        std::cout << i*1000000000 << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

gcc产生以下警告:

warning: iteration 3u invokes undefined behavior [-Waggressive-loop-optimizations]
   std::cout << i*1000000000 << std::endl;
                  ^
Run Code Online (Sandbox Code Playgroud)

我知道有一个有符号的整数溢出.

我不能得到的是为什么i价值被溢出操作打破了?

我已经阅读了为什么x86上的整数溢出与GCC导致无限循环的答案,但我仍然不清楚为什么会发生这种情况 - 我认为"未定义"意味着"任何事情都可能发生",但这种特定行为的根本原因是什么?

在线:http://ideone.com/dMrRKR

编译: gcc (4.8)

c++ gcc undefined-behavior

160
推荐指数
5
解决办法
6万
查看次数

为什么带有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 ++中的签名溢出和未定义的行为(UB)

我想知道以下代码的使用

int result = 0;
int factor = 1;
for (...) {
    result = ...
    factor *= 10;
}
return result;
Run Code Online (Sandbox Code Playgroud)

如果循环是随着n时间反复进行的,则将factor其乘以10精确的n时间。但是,factor仅在乘以10n-1次数后才使用。如果我们假设factor除了在循环的最后一次迭代之外永远不会溢出,而是可能在循环的最后一次迭代中溢出,那么这样的代码是否可以接受?在这种情况下,factor证明溢出后永远不会使用的值。

我正在就是否应接受此类代码进行辩论。可以将乘法放在if语句中,并且在可能溢出时,不对循环的最后一次迭代进行乘法。缺点是它会使代码混乱,并添加了一个不必要的分支,需要在所有先前的循环迭代中进行检查。我还可以减少循环迭代一次,并在循环之后复制一次循环主体,这又使代码复杂化。

有问题的实际代码在一个紧密的内部循环中使用,该循环在实时图形应用程序中消耗大量的总CPU时间。

c++

16
推荐指数
6
解决办法
862
查看次数

为什么这句话:"未定义的行为意味着编译器可以做任何想做的事情"是真的吗?

具体参考:https://blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p = 633 /

我是一名新的C++程序员,我目前正在学习未定义的行为及其对程序的影响.我特意链接到上面的博客,该博客说当发生未定义的行为时,任何事情都可能发生.

它特别提到了几次,当发生未定义的行为时,编译器可以允许任何事情发生.

具体是什么导致这种情况发生,为什么会发生?

c++ compiler-construction undefined-behavior

6
推荐指数
2
解决办法
321
查看次数

哪些整数运算不安全?

我的应用程序评估用户指定的一些整数表达式.我想检测所有潜在的错误并报告它们.

所有计算都在int64_t(签名)完成.式可以包括几乎所有的C++二进制运算符(+,-,*,/,%,|,||,&,&&,和六比较运算符)和整数(可能是负数).

问题是:在评估可能使我的程序终止的表达式时可能发生什么错误?我想出了其中两个:

  1. 除法(或模数)为零
  2. 分为std::numeric_limits<int64_t>::min()-1.

也可能出现有符号整数溢出,但是,据我所知,在这样的设置中它不能对大多数CPU做任何有害的事情,所以我们忽略它.

c++ arithmetic-expressions

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

需要一个关于递归的新观点

我无法绕过这个. 当第4行看起来相同时
,为什么这两个函数会产生截然不同的结果
呢?

版本I

int factorial(int val) // input=5; output=120
{
    if (val != 0)
        return factorial(val - 1) * val;
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

版本II

int factorial(int val) // input=5; output=0
{
    if (val != 0)
        return factorial(--val) * val;
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

c++ recursion

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