配列インデックスとポインタ演算の場合、ポインタと同じサイズの型(通常、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上のGCC4.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よりも多くのメモリを必要とします。そのような配列がある場合、ゼロ/符号拡張を回避するという比較的小さな利点よりもはるかにパフォーマンスに影響を与える可能性があります。わからない場合は、プロファイルしてください。