string [x] vs*string ++

Nee*_*ran 7 c

理论上两种方法中哪一种更快,为什么?(指向字符串的指针必须是常量.)

destination [count]和*destination ++之间的确切区别是什么?目的地[count]是否会在每次通话时从0移动到计数?*destination ++只是在每次通话时加1吗?

char *const string = "Hello world!";
char *destination = malloc(strlen(string) + 1);
int count = 0;
while(string[count] != '\0')
{
    destination[count] = string[count];

    count++;
}

char *const string = "Hello world!";
char *destination = malloc(strlen(string) + 1);
char *ptr = string;
while(*ptr != '\0')
{
    *destination++ = *ptr++;
}
Run Code Online (Sandbox Code Playgroud)

pto*_*ato 6

这取决于编译器.使用现代编译器,实际上无法在单指令级别上预测任何有关优化的内容,而无需实际查看生成的代码.两者都可能编译为等效指令.

也就是说,每次调用destination[count]都不会从0循环到count每次调用.它需要内存位置destination[0],增加count类型大小的时间*destination,并在那里查看.(当然,这很天真地说 - 编译器可能会做得更快.)

在另一方面,*destination++需要的存储位置destination[0](这是不是数组的开始了,因为你已经改变destination),看上去那里,并添加类型的大小*destination,使destination[0]指的是什么曾经是destination[1].


J-1*_*DiZ 5

在过去的好时光,第二种方法更快.但是使用现代编译器优化,它们是一样的.

这是因为:

destination[count] = string[count];
Run Code Online (Sandbox Code Playgroud)

会做的

*(destination+count) = *(string+count);
Run Code Online (Sandbox Code Playgroud)

add每个循环需要再操作两次.现代编译器会为你做这件事.


Don*_*ows 5

我们为什么要推测?我们可以尝试并找出答案.我用gcc -O3 -g(在x86上)编译代码并反汇编结果.有比我预期的更多的变化,所以我将集中在中间的位置,我们期望两者之间的大部分差异.第一种情况下循环的核心:

0x00000030 <foo+48>:    mov    %dl,(%edi,%esi,1)
0x00000033 <foo+51>:    movzbl 0x1(%ecx),%edx
0x00000037 <foo+55>:    inc    %eax
0x00000038 <foo+56>:    inc    %ecx
0x00000039 <foo+57>:    mov    %eax,%esi
0x0000003b <foo+59>:    test   %dl,%dl
0x0000003d <foo+61>:    jne    0x30 <foo+48>
Run Code Online (Sandbox Code Playgroud)

第二种情况下循环的核心:

0x00000080 <foo2+48>:   mov    %dl,(%eax)
0x00000082 <foo2+50>:   movzbl 0x1(%ecx),%edx
0x00000086 <foo2+54>:   inc    %eax
0x00000087 <foo2+55>:   inc    %ecx
0x00000088 <foo2+56>:   test   %dl,%dl
0x0000008a <foo2+58>:   jne    0x80 <foo2+48>
Run Code Online (Sandbox Code Playgroud)

在此基础上,第二个可能会快一点.但实际上,它在实践中不会产生太大的影响.L1缓存保持两个循环都很好,目标内存未缓存,因此差异没有实际意义.祝你好好实际测量两者之间的差异.