Ich hatte die Angewohnheit, int zu verwenden, um auf Arrays zuzugreifen (besonders in for-Schleifen); allerdings habe ich kürzlich entdeckt, dass ich möglicherweise "alles falsch gemacht" habe und mein x86-System die Wahrheit vor mir verborgen hat. Es stellt sich heraus, dass int in Ordnung ist, wenn sizeof(size_t) == sizeof(int)
ist, aber wenn es auf einem System verwendet wird, auf dem sizeof(size_t) > sizeof(int)
ist, führt es zu einer zusätzlichen mov
-Instruktion. size_t und ptrdiff_t scheinen der optimale Weg auf den von mir getesteten Systemen zu sein, da sie keiner zusätzlichen mov
-Instruktion bedürfen.
Hier ist ein verkürztes Beispiel
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
OK, ich habe mich selbst repariert (verwende jetzt size_t und ptrdiff_t), aber wie finde ich diese Stellen in meinem Code (hoffentlich nicht manuell), damit ich sie reparieren kann?
Kürzlich habe ich festgestellt, dass mehrere Patches mit Änderungen von int
zu size_t
über den Draht gegangen sind, die Clang erwähnen.
Ich habe eine Tabelle der zusätzlichen Instruktionen zusammengestellt, die in jeder Instanz eingefügt werden, um die Ergebnisse von "alles falsch gemacht" zu zeigen.
char<br> short<br> int<br>unsigned<br> char<br>unsigned<br> short<br>unsigned<br> int movsbq %sil, %rsi<br>movswq %si, %rsi<br>movslq %esi, %rsi<br><br>movzbl %sil, %esi <br><br>movzwl %si, %esi <br><br>movl %esi, %esi <br><br>Tabelle der unerwünschten Bewegungsoperationen beim<br>Zugriff auf Vektoren mit "falschem" Typ.
Hinweis: long
, long long
, unsigned long
, unsigned long long
, size_t
und ptrdiff_t
benötigen keine zusätzliche mov*-Operation (im Grunde alles >= Größe des größten Objekts oder 8 Bytes auf dem 64-Bit-Referenzsystem)
Bearbeitet:
Ich glaube, ich habe einen praktikablen Stub zum Patchen von gcc erstellt, aber ich kenne mich nicht im Quellcode aus, um den Stub zu vervollständigen und ordnungsgemäße -Wflag-Bits hinzuzufügen, und wie üblich ist der schwierigste Teil des Programmierens das Benennen von Dingen. -Wunalinged-index?
gcc/c/c-typeck.c <strong>___</strong>
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 <strong>_____</strong>
trigraphs
C ObjC C++ ObjC++
-trigraphs Support ISO C trigraphs
>
> Wunaligned-index
> C ObjC C++ ObjC++
> Warnen bei Arrayindizes kleiner als size_t
undef
C ObjC C++ ObjC++ Var(flag_undef)
Systemspezifische und GCC-spezifische Makros nicht vordefinieren
gcc/c-family/c-opts.c <strong>__</strong>
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;