对于数组索引和指针运算,与指针大小相同的类型(通常是 size_t 和 ptrdiff_t)可能会更好,因为它们避免了对寄存器进行零或符号扩展的需要。考虑
float onei(float *a, int n)
{
return a[n];
}
float oneu(float *a, unsigned n)
{
return a[n];
}
float onep(float *a, ptrdiff_t n)
{
return a[n];
}
float ones(float *a, size_t n)
{
return a[n];
}
在 x86_64 上使用 GCC 4.4 -O2 会生成以下 asm:
.p2align 4,,15
.globl onei
.type onei, @function
onei:
.LFB3:
.cfi_startproc
movslq %esi,%rsi
movss (%rdi,%rsi,4), %xmm0
ret
.cfi_endproc
.LFE3:
.size onei, .-onei
.p2align 4,,15
.globl oneu
.type oneu, @function
oneu:
.LFB4:
.cfi_startproc
mov %esi, %esi
movss (%rdi,%rsi,4), %xmm0
ret
.cfi_endproc
.LFE4:
.size oneu, .-oneu
.p2align 4,,15
.globl onep
.type onep, @function
onep:
.LFB5:
.cfi_startproc
movss (%rdi,%rsi,4), %xmm0
ret
.cfi_endproc
.LFE5:
.size onep, .-onep
.p2align 4,,15
.globl ones
.type ones, @function
ones:
.LFB6:
.cfi_startproc
movss (%rdi,%rsi,4), %xmm0
ret
.cfi_endproc
.LFE6:
.size ones, .-ones
可以看出,具有 int 和 unsigned int 索引(onei 和 oneu)的版本需要额外的指令(movslq/mov)来对寄存器进行符号/零扩展。
正如评论中提到的,缺点是对 64 位寄存器进行编码比 32 位部分占用更多空间,从而使代码体积膨胀。其次,ptrdiff_t/size_t 变量比等效的 int 需要更多的内存;如果你有这样的数组,它肯定会影响性能,而不是避免零/符号扩展的相对较小的好处。如果不确定,请配置文件!