我在godbolt上编译这段代码。orgwith-O2和编译器不会使用一些memcpy对其进行优化,而是诚实地运行循环。
void foo(int* dst, int* src, int n)
{
for (int i = 0; i < n; ++i)
{
dst[i] = src[i];
}
}
但是,如果我将“= src[i]”替换为“= 0”,他们会使用memset。但同样,当我用“ = 1”替换它时,它们会运行一个循环。当要设置的值不为零时,为什么它们会避免使用 memcpy 和 memset?我认为这是他们将执行的第一批优化之一。
来完成@MilesBudnek的好答案:
< code>memset以字节粒度工作,而您使用的< code>int通常大于1个字节(4个字节)。这就是为什么编译器不容易用内存集替换赋值< code>= 1的原因。
另请注意,-O2
不能为GCC启用矢量化,尽管它显然可以为Clang启用矢量化。-ftree-vectorize
(包含在-O3
中)是GCC生成更快的SIMD指令所必需的(在许多平台上不如memcpy
/memmobile
/memset
快)。
src
和dest
指向的范围可能重叠,在这种情况下,
的行为将未定义。因此,将此函数优化为只调用
memcpy
是不合适的。
memmove
是合适的,但当src
和
ranges重叠时,它的行为与函数不同。考虑以下内容:
int arr[5] = {1, 2, 3, 4, 5};
foo(arr + 1, arr, 4);
您的函数将在调用后产生包含< code>{1,1,1,1,1}的< code>arr,而< code>memmove被指定为产生包含< code>{1,1,2,3,4}的< code>arr。因此,编译器也不能将< code>foo优化为对< code>memmove的调用。
C在C99中添加了< code>restrict关键字,告诉编译器两个范围不会重叠,但是C并没有采用这个特性。
在 C 或 C 中,如果编译器遇到一个 循环,其中计数器从 计数到 n, n 是一个变量(不是函数调用,也不是常量),编译器是否会通过检查变量 (绑定变量)是否会在循环期间更改(访问写入, 例如: 可以是循环前计算的字符串的长度),通过优化这里,我的意思是将其值复制到寄存器以避免内存访问? 下面是一个示例: 编译器会注意到这一点并对其进行优化吗?
本文向大家介绍C/C++ 编译器优化介绍,包括了C/C++ 编译器优化介绍的使用技巧和注意事项,需要的朋友参考一下 0. gcc -o gcc -o 的优化仍然是机械的,想当然的。只有做到深入理解计算机系统,加深对编程语言的理解,才能写出最优化的代码。 Linux下gcc 优化级别的介绍 · gcc -o0 ⇒ 不提供任何优化; · gcc -o1 ⇒ 最基本的优化,主要对代码的分支、表达式、
我有一些遗留代码,其中包含一个浪费时间的循环,以便有时间完成eeprom读取(不好的做法): 但是,当为了提高速度而打开编译器优化时,会发生一些奇怪的事情。它不一定与该语句相关联,但我想知道编译器是否可能只是优化了时间延迟
考虑下面的代码片段 通过-O3优化,最新的gcc和clang版本没有优化指向包装器的指针、指向底层函数的指针。参见第22行的组装: 在后面的+中,编译器将指针放置到,而不只是。 编辑2。同样模式的更简单的例子: gcc 8.2通过抛出指向包装器的指针并将直接存储在其位置(https://gcc.godbolt.org/z/nmibeo)成功地优化了这段代码。然而,按照注释更改代码行(即手动执行相同
本文向大家介绍C#中尾递归的使用、优化及编译器优化,包括了C#中尾递归的使用、优化及编译器优化的使用技巧和注意事项,需要的朋友参考一下 递归运用 一个函数直接或间接的调用自身,这个函数即可叫做递归函数。 递归主要功能是把问题转换成较小规模的子问题,以子问题的解去逐渐逼近最终结果。 递归最重要的是边界条件,这个边界是整个递归的终止条件。 上面是个经典阶乘函数的实现。这里分2步: 1.转换,把10的阶
我想开始在c#中开发,但是我使用Linux和VSCode进行开发,由于一些错误,我找不到答案,VSCode不运行代码,所以我决定借助这个链接(在linux终端上运行C#代码)来制作一个bash脚本来完成这部分代码: 到目前为止,我是这样做的: 它确实可以工作,但是我想让2美元(第二个参数)自动以1美元(第一个参数)命名,因此我不需要写2美元的值,只需写1美元创建一个同名的exe并用mono运行该e