我经常注意到gcc将乘法转换为可执行文件中的移位.当乘以a int和a 时,可能会发生类似的事情float.例如,2 * f可能只是将指数递增f1,从而节省了一些周期.编译器,也许是一个人请求他们这样做(例如通过-ffast-math),一般来说,这样做吗?
编译器通常是否足够聪明,或者我是否需要使用scalb*()或ldexp()/frexp()函数系列自己完成此操作?
我正在更新一些旧代码,并且发现了几个实例,每次需要调用其中一个属性或方法时,都会重复转换相同的对象.例:
if (recDate != null && recDate > ((System.Windows.Forms.DateTimePicker)ctrl).MinDate)
{
((System.Windows.Forms.DateTimePicker)ctrl).CustomFormat = "MM/dd/yyyy";
((System.Windows.Forms.DateTimePicker)ctrl).Value = recDate;
}
else
{
(System.Windows.Forms.DateTimePicker)ctrl).CustomFormat = " ";
}
((System.Windows.Forms.DateTimePicker)ctrl).Format = DateTimePickerFormat.Custom;
Run Code Online (Sandbox Code Playgroud)
我倾向于修复这种怪异,但考虑到我有限的时间,我不想打扰任何不影响功能或性能的东西.
所以我想知道的是,这些冗余的演员是否被编译器优化了?我试着用一个简单的例子使用ildasm自己搞清楚,但不熟悉IL我只是更加困惑.
UPDATE
到目前为止,共识似乎是a)不,演员表没有优化,但b)虽然可能会有一些小的性能影响因此,它不太可能显着,并且c)我应该考虑修复它们无论如何.如果我有时间的话,我有一天会解决这些问题.同时,我不会担心他们.
感谢大家!
当函数涉及重新分配时,我发现一些编译器可能在函数调用之前保存地址.它导致存储在无效地址中的返回值.
在上面的描述中有一个例子来解释行为.
#include <stdio.h>
#include <vector>
using namespace std;
vector<int> A;
int func() {
A.push_back(3);
A.push_back(4);
return 5;
}
int main() {
A.reserve(2);
A.push_back(0);
A.push_back(1);
A[1] = func();
printf("%d\n", A[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有一些常见的C++编译器,测试结果如下.
155是不确定的行为?
我遇到了代码中的错误,只有在启用了优化的情况下构建代码时才会重现.我制作了一个控制台应用程序来复制测试逻辑(下面的代码).你会看到,当启用优化时,'value'在执行这个无效逻辑后变为null:
if ((value == null || value == new string[0]) == false)
Run Code Online (Sandbox Code Playgroud)
修复是直截了当的,并在违规代码下方注释掉.但是......我更担心的是我可能遇到了汇编程序中的错误,或者其他人可能会解释为什么将值设置为null.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace memory_testing
{
class Program
{
sta tic void Main(string[] args)
{
while(true)
{
Console.Write("Press any key to start...");
Console.ReadKey();
Console.WriteLine();
PrintManagerUser c = new PrintManagerUser();
c.MyProperty = new string[1];
}
}
}
public class PrintManager
{
public void Print(string key, object value)
{
Console.WriteLine("Key is: " + key);
Console.WriteLine("Value is: " + value);
}
}
public class PrintManagerUser …Run Code Online (Sandbox Code Playgroud) 我很好奇编译器在优化时的自由度.让我们将这个问题限制在GCC和C/C++(任何版本,任何标准版本):
是否有可能根据编译的优化级别编写行为不同的代码?
我想到的例子是在C++中的各种构造函数中打印不同的文本位,并根据副本是否被删除而获得差异(尽管我无法使这样的东西工作).
不允许计数时钟周期.如果你有一个非GCC编译器的例子,我也很好奇,但我无法检查它.C中的示例的奖励积分:-)
编辑:示例代码应该是标准兼容的,并且从一开始就不包含未定义的行为.
编辑2:已经有了一些很棒的答案!让我稍微了解一下:代码必须构成一个格式良好的程序并且符合标准,并且必须在每个优化级别编译为正确的,确定性的程序.(这不包括形状不规则的多线程代码中的竞争条件等.)我也理解浮点舍入可能会受到影响,但让我们对此进行折扣.
我只获得了800点声望,所以我认为我将在第一个完整的例子中赢得50点声望以符合这些条件的(精神); 25如果涉及滥用严格别名.(视某人向我展示如何向他人发送赏金.)
我记得在某处可以真正优化和加速代码的某些部分,程序员用汇编语言编写该部分.我的问题是 -
我正在努力理解这个概念,非常感谢任何帮助或链接.
更新:根据dbemerlin的要求改写第3点 - 因为您可能能够编写比编译器生成的更有效的汇编代码,但除非您是汇编专家,否则您的代码运行速度会慢,因为编译器通常会比大多数人更好地优化代码.
我只是尝试在VS2010上编译几个C++片段并分析IDA Pro上的可执行文件.我注意到的是,他们中的大多数在开始时都有类似的内容(在调用__security_check_cookie之后不久)
xor eax, ebp
和类似的东西
xor ecx, ebp
在底部.为什么会这样?编译器优化已关闭.
c++ assembly reverse-engineering buffer-overflow compiler-optimization
在最近关于如何优化某些代码的讨论中,我被告知将代码分解为许多小方法可以显着提高性能,因为JIT编译器不喜欢优化大型方法.
我不确定这一点,因为看起来JIT编译器本身应该能够识别自包含的代码段,而不管它们是否在他们自己的方法中.
任何人都可以确认或驳斥这一说法吗?
我有一个AsIterator模板类,它采用类似数字的类型,在这个例子中只是一个int,并将其转换为迭代器(++并--递增和递减数字,并operator*只返回对它的引用).
这工作正常,除非它被包装成a std::reverse_iterator并使用任何优化编译(-O足够).当我优化二进制文件时,编译器去除reverse_iterator对它的取消引用调用,并用一些奇怪的值替换它.必须注意的是,它仍然可以进行正确的迭代次数.它只是反向迭代器获得的值,即垃圾.
请考虑以下代码:
#include <iterator>
#include <cstdio>
template<typename T>
class AsIterator : public std::iterator<std::bidirectional_iterator_tag, T> {
T v;
public:
AsIterator(const T & init) : v(init) {}
T &operator*() { return v; }
AsIterator &operator++() { ++v; return *this; }
AsIterator operator++(int) { AsIterator copy(*this); ++(*this); return copy; }
AsIterator &operator--() { --v; return *this; }
AsIterator operator--(int) { AsIterator copy(*this); …Run Code Online (Sandbox Code Playgroud) 下面的 square 实现会产生一系列 cmp/je 语句,就像我期望的链式 if 语句一样:
int square(int num) {
if (num == 0){
return 0;
} else if (num == 1){
return 1;
} else if (num == 2){
return 4;
} else if (num == 3){
return 9;
} else if (num == 4){
return 16;
} else if (num == 5){
return 25;
} else if (num == 6){
return 36;
} else if (num == 7){
return 49;
} else {
return num * num; …Run Code Online (Sandbox Code Playgroud)