2012-08-13 13 views
7

Bei der Implementierung eines Menüs auf einem eingebetteten System in C (++) (AVR-Gcc), endete ich mit Void-Funktion Zeiger, die Argumente, und in der Regel nutzen sie.Wie teuer sind NULL-Zeigerargumente?

// void function prototype 
void (*auxFunc)(char *); 

In einigen Fällen (in der Tat nicht wenige), die Funktion braucht eigentlich nicht das Argument, also würde ich so etwas tun:

if (something) doAuxFunc(NULL); 

Ich weiß, ich könnte nur eine Überlastung anderer Funktionstyp, aber ich versuche tatsächlich, dies nicht zu tun, da ich mehrere Objekte instanziiere und sie leicht halten möchte.

Ist das Aufrufen mehrerer Funktionen mit NULL-Zeigern (wenn sie für einen tatsächlichen Zeiger gedacht sind) schlimmer als die Implementierung viel mehr Funktionsprototypen?

+6

Was sagt der Profiler? – zoul

+2

Warum sind Überladungen "schwer"? –

+0

@KerrekSB Hauptsächlich, weil es (relativ) viele Objekte gibt, die diese enthalten, und Raum ist wertvoll für eingebettete Systeme. In diesem Fall ist ein Menü eher ein Hilfsteil der Hauptfunktionalität des Projekts. – falro

Antwort

9

Die Überprüfung auf NULLs ist ein sehr geringer Overhead auch auf einem Mikrocontroller - Vergleich gegen 0 soll blitzschnell sein. Wenn Sie mehrere Funktionen überladen, werden Sie die Lesbarkeit für (eine sehr leichte) Verbesserung der Leistung durchkreuzt. Lass den Optimierer von GCC einfach seine Sachen machen, es ist ziemlich gut :)

1

Ich denke, der "Kompromiss" ist lächerlich niedrig für jeden Ansatz, aber dies ist die Zeit, Benchmarks für dich selbst zu machen. Wenn Sie dies tun, bitte posten Sie einige Ergebnisse :)

2

Überprüfung auf 0 ist wirklich billig, Überladung ist noch billiger, da es bei der Kompilierung entschieden wird, welche Funktion zu wählen.

Aber wenn Sie denken, dass Ihre Schnittstellen zu kompliziert mit Überladung werden und Ihre Funktion klein ist, sollten Sie es inline deklarieren und es in eine Kopfzeile setzen. Checkig für 0 kann dann leicht von jedem anständigen modernen Compiler weg optimiert werden.

+0

Da dies eine Lösung für ein Embedded-System ist, würde Inlining dazu führen, dass mehr Code-Speicher verwendet wird, der in diesem Fall ebenfalls teuer ist. – syplex

+0

@Syplex: Das hängt sehr von der Größe des Funktionsaufrufs und der Bereinigung ab. Inlining kann Platz sparen.Dies ist insbesondere dann der Fall, wenn ein sinnvoller Optimierer dann unnötige Anweisungen beseitigen kann. Ein allgemeines einfaches Beispiel ist eine 'Foo :: getBar'-Methode, die schreibgeschützten Zugriff auf das Bar-Mitglied in Foo bietet. Dies kann als eine einfache Zeigerversatzberechnung enden und könnte sogar mit anderen Versatzberechnungen gefaltet werden. – MSalters

+0

gcc hat jetzt die Funktion, eine partielle Inlining zu machen. Im Grunde erstellt es einen Funktionskern, der von allen Parametern abhängt und dann den Teil, der konstant propagiert werden kann. Dies hat nicht viel Overhead. –

3

Betrachten Sie die Disassembly, sollte es eine Null (Null) als erstes Argument übergeben, die entweder ein Register oder einen Stapelspeicherort brennt, wenn es ein Register brennt, dann kann es kosten Sie einen Push und Pop wenn Die aufrufende Funktion hungert nach Registern. (Wenn Sie nur einen Funktionsaufruf verwenden, kostet es Sie Pushs und Pops, wenn die Funktion nach Registern hungert, um die Aufrufkonvention zu implementieren).

Es ist also wahrscheinlich eine Kosten, aber es kann nicht genug Kosten zu ändern, wie Sie Dinge tun.