c - 为什么字符串文字比静态字符数组更快?

标签 c benchmarking

我进行了以下测试。

charspeed.c

#include <stdio.h>
#include <time.h>

#define CHAR_COUNT 26
#define CHAR_LIST "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
static const char *CHAR_ARRAY = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

#define RUN_COUNT 1000000000

#define GET_CLOCK (float)clock() / CLOCKS_PER_SEC

int main()
{
    long long int sum = 0;
    float start, end;

    start = GET_CLOCK;
    for (size_t i = 0; i < RUN_COUNT; i++)
    {
        char test = CHAR_LIST[i % CHAR_COUNT];
        sum += test; // Force the loop to run!
    }
    end = GET_CLOCK;
    printf("#define Time: %f\n", end - start);

    start = GET_CLOCK;
    for (size_t i = 0; i < RUN_COUNT; i++)
    {
        char test = CHAR_ARRAY[i % CHAR_COUNT];
        sum += test; // Must be the same as fist loop!
    }
    end = GET_CLOCK;
    printf("static const *CHAR_ARRAY Time: %f\n", end - start);
    printf("sum = %lld\n", sum); // Must access "sum" after loops!
    return 0;
}

它的输出

#define 时间:1.741000
static const *CHAR_ARRAY 时间:1.868000

为什么使用 #define 指令的字符串文字比预初始化的静态字符数组更快?字符串文字到底存储在哪里以及为什么在 block 范围内访问它们更快?

使用的编译器选项是gcc -o charspeed charspeed.c

最佳答案

只是一个补充答案来完成其他答案。

字符串文字不是 const char * 。 原因是 const char *可以重新分配。在你的情况下,这意味着你可以这样做 CHAR_ARRAY = "foo"; .

实际上,这意味着编译器无法优化处理 const char * 的代码。比处理字符串文字的代码。

要解决此问题,您可以使用以下方法之一:

const char *const CHAR_ARRAY = "...";
const char CHAR_ARRAY[] = "...";

这应该保证与字符串文字相同的性能。

但是,在您的情况下,由于您声明 CHAR_ARRAYstatic ,这意味着编译器可以只查看当前源文件,如果 CHAR_ARRAY可以重新分配给。

实际上,这意味着,假设启用优化:

  • 对于字符串文字, const char *constconst char[] ,将生成相同的汇编代码(A)。
  • 对于非静态 const char *将生成不同的汇编代码 (B),可能会更慢,因为它们是附加的间接寻址,并且在编译时无法知道结果。
  • 对于 static const char * ,它将使用汇编代码 (A) 或 (B),具体取决于编译器是否可以证明指针可能被重新分配。例如,如果您添加一个函数 void f() { CHAR_ARRAY = "foo"; }在代码中的任何地方,如果禁止编译器使用程序集 (A),则将使用 (B)。

关于c - 为什么字符串文字比静态字符数组更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58051488/

相关文章:

c - 当我在 C 和 Ubuntu 中使用 fork() 时,Vlc 库失败

C - 系统调用 - N 个子进程的数组分区 -

c++ - 在 C 中警告 c4307 积分常量溢出

objective-c - 变量参数列表中的非 POD 类型

python - 如何在 Python 中的列表中安排不同时间的操作

apache - 如何使用 Linux 对 Web 服务器进行基准测试/负载测试

c++ - fcntl() 中的第三个参数是什么

java - MySQL JDBC 查询比 JMH 测试中应有的速度快得多

c# - 为什么循环 Array.AsSpan() 更快?

c++ - 已知大小时向 vector 添加元素的基准测试