我有使用 int 访问数组的习惯(尤其是在 for 循环中);然而我最近发现我可能一直“做错了”,而且我的 x86 系统一直向我隐瞒真相。事实证明 int 没问题sizeof(size_t) == sizeof(int)
但当在系统上使用时sizeof(size_t) > sizeof(int)
,它会导致额外的mov
操作说明。 size_t 和 ptrdiff_t 似乎是我测试过的系统上的最佳方式,不需要额外的mov
.
这是一个简短的示例
int vector_get(int *v,int i){ return v[i]; }
> movslq %esi, %rsi
> movl (%rdi,%rsi,4), %eax
> ret
int vector_get(int *v,size_t i){ return v[i]; }
> movl (%rdi,%rsi,4), %eax
> ret
好的,我已经修复了自己(现在使用 size_t 和 ptrdiff_t),现在我如何(希望不是手动)在我的代码中找到这些实例,以便我可以修复它们?
最近我注意到几个补丁,包括来自int
to size_t
电话里提到了 Clang。
我将在每个实例上插入的额外指令放在一起,以显示“全部错误”的结果。
char
short
int
unsigned
char
unsigned
short
unsigned
int
movsbq %sil, %rsi
movswq %si, %rsi
movslq %esi, %rsi
movzbl %sil, %esi
movzwl %si, %esi
movl %esi, %esi
Table of unwanted move operations when
accessing vectors with "wrong" type.
Note: long
, long long
, unsigned long
, unsigned long long
, size_t
and ptrdiff_t
不需要额外的 mov* 操作(基本上任何 >= 最大对象大小,或 64 位参考系统上的 8 个字节)
Edit:
我想我可能有一个可行的存根来修补 gcc,但我不知道如何围绕它的源代码来完成存根并添加适当的 -Wflag 位,并且像往常一样,编程中最困难的部分是命名内容。 -Wunalinged-索引?
gcc/c/c-typeck.c _______________________________________________
if (!swapped)
warn_array_subscript_with_type_char (index);
>
> if ( sizeof(index) < sizeof(size_t) )
> warning_at (loc, OPT_Wunaligned_index,
> "array index is smaller than size_t");
/* Apply default promotions *after* noticing character types. */
index = default_conversion (index);
gcc/c-family/c.opt _____________________________________________
trigraphs
C ObjC C++ ObjC++
-trigraphs Support ISO C trigraphs
>
> Wunaligned-index
> C ObjC C++ ObjC++
> Warn about array indices smaller than size_t
undef
C ObjC C++ ObjC++ Var(flag_undef)
Do not predefine system-specific and GCC-specific macros
gcc/c-family/c-opts.c __________________________________________
case OPT_Wtrigraphs:
cpp_opts->warn_trigraphs = value;
break;
>
> case OPT_Wunaligned_index:
> cpp_opts->warn_unaligned_index = value;
>
case OPT_Wundef:
cpp_opts->warn_undef = value;
break;