c - 使用算术比存储变量更快吗?

标签 c optimization bit-manipulation

在 C 语言中(或者一般情况下),使用算术获取值或从数组/变量调用它更快吗?

例如,如果我有

int myarray[7] = {16};
int mysixteen = 16;

然后我可以通过多种不同的方式得到 16

myarray[#]
mysixteen
16
1 << 4
10 + 6

从逻辑上讲,16 是最快的,但对于一组数字来说,这并不总是方便或合理。这可能相关的一个例子是预计算表。假设您需要 64 位的位掩码,您可以填充一个数组

for (int i = 0; i < 64; ++i) {
    mask[i] = 1 << i;
}

并在将来调用该数组,或者创建一个宏

#define mask(b) (1 << b)

并称之为。

最佳答案

一般来说,任何一个

  • 16
  • 1 << 4
  • 10 + 6

将产生文字16,因为编译器肯定会实现名为 constant folding 的优化。 .

性能

  • 我的十六岁
  • myarray[n]

可能较低,具体取决于这些变量值的存储位置。在内存中?如果是,该内存是否位于任何 CPU 缓存中?或者它存储在CPU寄存器之一中?没有明确的答案。

一般来说,对于特定程序,您始终可以看到编译器为您提供的内容 - 但请注意,这可能会根据周围的代码和优化标志而发生很大变化。

要亲自尝试一下,请考虑这个小程序:

int f() { return 16; }

int g() { return 1 << 4; }

int h() { return 10 + 6; }

int i() {
    int myarray[7] = { 16 };
    return myarray[3];
}

int j() {
    int mysixteen = 16;
    return mysixteen;
}

如果我使用 gcc 4.7.2 编译它,然后检查反汇编,例如

$ gcc -c so19802742.c -o so19802742.o
$ objdump --disassemble so19802742.o

我明白了:

0000000000000000 <f>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   b8 10 00 00 00          mov    $0x10,%eax
   9:   5d                      pop    %rbp
   a:   c3                      retq   

000000000000000b <g>:
   b:   55                      push   %rbp
   c:   48 89 e5                mov    %rsp,%rbp
   f:   b8 10 00 00 00          mov    $0x10,%eax
  14:   5d                      pop    %rbp
  15:   c3                      retq   

0000000000000016 <h>:
  16:   55                      push   %rbp
  17:   48 89 e5                mov    %rsp,%rbp
  1a:   b8 10 00 00 00          mov    $0x10,%eax
  1f:   5d                      pop    %rbp
  20:   c3                      retq   

0000000000000021 <i>:
  21:   55                      push   %rbp
  22:   48 89 e5                mov    %rsp,%rbp
  25:   48 c7 45 e0 00 00 00    movq   $0x0,-0x20(%rbp)
  2c:   00 
  2d:   48 c7 45 e8 00 00 00    movq   $0x0,-0x18(%rbp)
  34:   00 
  35:   48 c7 45 f0 00 00 00    movq   $0x0,-0x10(%rbp)
  3c:   00 
  3d:   c7 45 f8 00 00 00 00    movl   $0x0,-0x8(%rbp)
  44:   c7 45 e0 10 00 00 00    movl   $0x10,-0x20(%rbp)
  4b:   8b 45 ec                mov    -0x14(%rbp),%eax
  4e:   5d                      pop    %rbp
  4f:   c3                      retq   

0000000000000050 <j>:
  50:   55                      push   %rbp
  51:   48 89 e5                mov    %rsp,%rbp
  54:   c7 45 fc 10 00 00 00    movl   $0x10,-0x4(%rbp)
  5b:   8b 45 fc                mov    -0x4(%rbp),%eax
  5e:   5d                      pop    %rbp
  5f:   c3                      retq   

请注意,由于常量折叠,fgh 会产生完全相同的机器代码。 i 中的数组访问会导致最多的机器代码(但不一定是最慢的!),而 j 则介于两者之间。

但是,这根本没有任何更复杂的代码优化!使用例如编译时生成的代码-O2 可能完全不同,因为编译器注意到对这五个函数中任何一个的调用都相当于仅使用常量16!

关于c - 使用算术比存储变量更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19802742/

相关文章:

c++ - GCC 似乎错过了简单的优化

php - 获取免费IP地址的算法

c - fflush() 始终返回 0 但将 errno 设置为 11(资源暂时不可用)

C 数独求解器通过回溯陷入困境

C 数据类型从 stdin 读取不同的输入并打印更改的数据

c++ - OpenCV CUDA C++ C 图像灰色

performance - 如何在基准测试中击败Go优化器?

javascript - 检查某个位置的位是否为1

c++ - 测试位是否在数字中重复

java - 在 Java 中更改 32 位整数的特定位