c - 有和没有辅助变量的变量交换——哪个更快?

标签 c assembly swap

我想你们都听说过“交换问题”; SO充满了关于它的问题。 不使用第三个变量的交换版本通常被认为更快,因为你少了一个变量。我想知道幕后发生了什么,并编写了以下两个程序:

int main () {
    int a = 9;
    int b = 5;
    int swap;

    swap = a;
    a = b;
    b = swap;

    return 0;
}

和没有第三个变量的版本:

int main () {
    int a = 9;
    int b = 5;

    a ^= b;
    b ^= a;
    a ^= b;

    return 0;
}

我使用 clang 生成了汇编代码并获得了第一个版本(使用第三个变量):

...
Ltmp0:
    movq   %rsp, %rbp
Ltmp1:
    movl   $0, %eax
    movl   $0, -4(%rbp)
    movl   $9, -8(%rbp)
    movl   $5, -12(%rbp)
    movl   -8(%rbp), %ecx
    movl   %ecx, -16(%rbp)
    movl   -12(%rbp), %ecx
    movl   %ecx, -8(%rbp)
    movl   -16(%rbp), %ecx
    movl   %ecx, -12(%rbp)
    popq   %rbp
    ret
Leh_func_end0:
...

这是第二个版本(不使用第三个变量):

...
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    movl   $0, %eax
    movl   $0, -4(%rbp)
    movl   $9, -8(%rbp)
    movl   $5, -12(%rbp)
    movl   -12(%rbp), %ecx
    movl   -8(%rbp), %edx
    xorl   %ecx, %edx
    movl   %edx, -8(%rbp)
    movl   -8(%rbp), %ecx
    movl   -12(%rbp), %edx
    xorl   %ecx, %edx
    movl   %edx, -12(%rbp)
    movl   -12(%rbp), %ecx
    movl   -8(%rbp), %edx
    xorl   %ecx, %edx
    movl   %edx, -8(%rbp)
    popq   %rbp
    ret
Leh_func_end0:
...

第二个更长,但我对汇编代码了解不多,所以我不知道这是否意味着它更慢,所以我想听听更了解它的人的意见。

以上哪个版本的变量交换速度更快且占用的内存更少?

最佳答案

查看一些优化的程序集。来自

void swap_temp(int *restrict a, int *restrict b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

void swap_xor(int *restrict a, int *restrict b){
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

gcc -O3 -std=c99 -S -o swapping.s swapping.c 产生

    .file   "swapping.c"
.text
.p2align 4,,15
.globl swap_temp
.type   swap_temp, @function
swap_temp:
.LFB0:
.cfi_startproc
movl    (%rdi), %eax
movl    (%rsi), %edx
movl    %edx, (%rdi)
movl    %eax, (%rsi)
ret
.cfi_endproc
.LFE0:
.size   swap_temp, .-swap_temp
.p2align 4,,15
.globl swap_xor
.type   swap_xor, @function
swap_xor:
.LFB1:
.cfi_startproc
movl    (%rsi), %edx
movl    (%rdi), %eax
xorl    %edx, %eax
xorl    %eax, %edx
xorl    %edx, %eax
movl    %edx, (%rsi)
movl    %eax, (%rdi)
ret
.cfi_endproc
.LFE1:
.size   swap_xor, .-swap_xor
.ident  "GCC: (SUSE Linux) 4.5.1 20101208 [gcc-4_5-branch revision 167585]"
.section    .comment.SUSE.OPTs,"MS",@progbits,1
.string "Ospwg"
.section    .note.GNU-stack,"",@progbits

对我来说,swap_temp 看起来尽可能高效。

关于c - 有和没有辅助变量的变量交换——哪个更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8567609/

相关文章:

c - 在双向链表中交换

c - gcc 分支预测

c - (反向)返回到 c 中的指定位置,程序集

java - Java 中的 SIGSEGV 能否使 JVM 不崩溃?

python - 实参校验性能影响

c - 编译器如何在堆栈上使用默认值为零来初始化本地数组?

继承场景下的C++交换问题

c++ - 在没有 #including 其库的情况下使用 swap()?

c - 用正确的整数类型替换数组访问变量

c++ - 从 64x64 位乘法中获得前 64 位的合理便携方式?