Frage

Die meisten Code, den ich je gelesen habe verwendet einen int für Standardfehlerbehandlung (Rückgabewerte von Funktionen und so weiter). Aber ich frage mich, ob es einen Nutzen aus der Verwendung eines uint_8 werden musste ist, wird ein Compiler - lesen: Die meisten C-Compiler auf den meisten Architekturen - produzieren Anweisungen, um die sofortige Adresse Modus - dh betten die 1-Byte-Ganzzahl in den Anweisung ? Der Schlüssel Anweisung über die ich denke wird der Vergleich nach einer Funktion, mit uint_8 als Rückgabetyp, kehrt zurück.

Ich kann über die Dinge falsch zu denken, als einen 1-Byte-Typs Einführung Ausrichtungsprobleme nur verursacht - es ist wahrscheinlich ein völlig gesund Grund, warum, wie die Dinge in 4-Bytes zu packen kompiliert und das ist vielleicht der Grund, warum jeder nur Ints verwendet -. und da dieses Problem im Zusammenhang stapeln anstatt dem Heap gibt es keinen wirklichen Aufwand

Das Richtige zu tun ist, was ich denke. Aber kann sagen, sagt sie für die Zwecke des Beweises dies ist ein beliebter billig Mikroprozessor für eine intelligente Uhr, und dass es mit 1k Speichern konfiguriert ist, aber hat verschiedene Adressierungsart in seinem Befehlssatz: D

Eine weitere Frage zu leicht die Diskussion (x86) spezialisiert wäre: ist die wörtliche in:

uint_32 x=func(); x==1;

und

uint_8 x=func(); x==1;

die gleiche Art? oder wird der Compiler einen 8-Byte-Literal im zweiten Fall erzeugen. Wenn dem so ist es es benutzen kann eine erzeugen Vergleichsanweisung, die das Literal als ein Zwischenwert, und der zurück int als Registerreferenz hat. CMP Siehe Befehlstypen. .

Eine weitere refference für den x86-Befehlssatz.

War es hilfreich?

Lösung

Hier ist, was ein bestimmte Compiler für den folgenden Code tun:

extern int foo(void) ;
void bar(void)
{
        if(foo() == 31) { //error code 31
                do_something();
        } else {
                do_somehing_else();
        }
}

   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   e8 fc ff ff ff          call   7 <bar+0x7>
   b:   83 f8 1f                cmp    $0x1f,%eax
   e:   74 08                   je     18 <bar+0x18>
  10:   c9                      leave
  11:   e9 fc ff ff ff          jmp    12 <bar+0x12>
  16:   89 f6                   mov    %esi,%esi
  18:   c9                      leave
  19:   e9 fc ff ff ff          jmp    1a <bar+0x1a>

eine 3-Byte-Anweisung für die cmp. wenn foo () ein Zeichen gibt, erhalten wir  b: 3c 1f cmp $ 0x1f,% al

Wenn Sie sich für Effizienz obwohl suchen. Gehen Sie nicht davon Zeug in% a1 Vergleich ist schneller als mit% eax Vergleich

Andere Tipps

Es kann zwischen den verschiedenen integralen Typen auf einer bestimmte Architektur sehr kleine Geschwindigkeitsunterschiede sein. Aber man kann sich nicht darauf verlassen, kann es ändern, wenn Sie auf einer anderen Hardware bewegen, und es kann sogar langsamer laufen, wenn Sie auf eine neuere Hardware aktualisieren.

Und wenn Sie über x86 im Beispiel sprechen Sie geben, machen Sie eine falsche Annahme: Eine unmittelbare Bedürfnisse des Typs uint8_t sein.

Eigentlich 8-Bit in den Befehl immediates eingebettet sind vom Typ int8_t und können mit Byte-, Wort- und dwords QWords verwendet werden, in C-Notation: char, short, int und long long

.

So auf dieser Architektur gebe es überhaupt keinen Nutzen, weder Codegröße noch die Ausführungsgeschwindigkeit.

Sie sollten int oder unsigned int-Typen für Ihre Berechnungen verwenden. Verwendung von nur kleineren Typen für Verbindungen (structs / arrays). Der Grund dafür ist, dass int ist normalerweise definiert als die „natürlichste“ Integral-Typ für den Prozessor, alle anderen abgeleiteten Typ Verarbeitung erforderlich machen kann korrekt zu arbeiten. Wir hatten in unserem Projekt mit gcc auf Solaris für SPARC den Fall zusammengestellt, die Zugriffe auf 8 und 16-Bit-Variable eine Anweisung an den Code hinzugefügt. Wenn eine kleinere Art aus dem Speicher geladen hatte es auf dem oberen Teil des Registers stellen Sie sicher, richtig eingestellt wurde (Vorzeichenerweiterung für signierten Typen oder 0 für unsigned). Dies machte den Code mehr und erhöhten Druck auf die Register, die die anderen Optimierungen verschlechtert.

Ich habe ein konkretes Beispiel bekam:

erklärte ich zwei Variable einer Struktur als uint8_t und bekam diesen Code in Sparc Asm:

    if(p->BQ > p->AQ)

wurde übersetzt in

ldub    [%l1+165], %o5  ! <variable>.BQ,
ldub    [%l1+166], %g5  ! <variable>.AQ,
and     %o5, 0xff, %g4  ! <variable>.BQ, <variable>.BQ
and     %g5, 0xff, %l0  ! <variable>.AQ, <variable>.AQ
cmp     %g4, %l0    ! <variable>.BQ, <variable>.AQ
bleu,a,pt %icc, .LL586  !

Und hier, was ich habe, wenn ich die beiden Variablen als uint_t erklärt

lduw    [%l1+168], %g1  ! <variable>.BQ,
lduw    [%l1+172], %g4  ! <variable>.AQ,
cmp     %g1, %g4    ! <variable>.BQ, <variable>.AQ
bleu,a,pt %icc, .LL587  !

Zwei arithmetische Operationen weniger und 2 Register mehr für andere Sachen

Prozessoren mögen typischerweise mit ihren natürlichen Registergrößen arbeiten, die in C ‚int‘.

Zwar gibt es Ausnahmen, die Sie auf ein Problem zu viel denken, das nicht existiert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top