PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Public variable erst später initialisieren



C_Classic
05.09.2010, 23:17
Hallo,
ich möchte in meinem Programm eine Public variable erst zu einem bestimmten Zeitpunkt initialisieren.
Soll heißen: Ich hab eine Funktion appStart(), eine appProc() und eine appProcFocus(). Nun wird aus main() erst appStart() und dann in einer Schleife appProc() aufgerufen. Ebenfalls wird appProcFocus() unter best. Umständen aufgerufen. Nun müssen diese Funktionen unter einander kommunizieren, jedoch sollen die variablen erst mit appStart() initialisiert werden (RAM sparen).
Wie kann ich es also schaffen public variablen während dem Betrieb zu erstellen (/danach auch wieder zu löschen)?

Danke schon mal im vorraus.
C_Classic


Ps: Bin grad im Urlaub - kann eure antworten also nicht gleich ausprobieren.

MichaF
06.09.2010, 11:50
Da wirst du um malloc() nicht herum kommen. Damit reservierst du einen Speicherbereich zur Laufzeit. Deine Aufgabe ist es nun, den anderen Funktionen die Zugriff auf diesen Bereich brauchen per Pointer die Position im Speicher mitzuteilen. Ob du dadurch wirklich RAM sparst wage ich allerdings zu bezweifeln, insbesondere wenn man an die vielen Probleme denkt, die malloc so mit sich bringt ;)

BurningWave
06.09.2010, 15:06
Es kommt darauf an, wo deine Variable definiert ist. Ich nehme mal an, dass sie gleich am Anfang vin main() deklariert wird. An deiner Stelle würde ich sie auch als normale Variable erstellen und als Pointer an die Funktionen übergeben, da mir nicht ganz klar ist, wo du duch ein späteres Initialisieren RAM sparst. Alternativ definierst du in main() einen Pointer, den du deinen Funktionen übergibst, die Init-Funktion reserviert mittels malloc() speicher für den Pointer. Vor Programmende muss dieser aber mit free() wieder freigegeben werden.

Felix G
06.09.2010, 20:07
Ganz ehrlich, mit malloc() RAM sparen zu wollen ist doch ein sehr ... esoterischer Ansatz ;-)

Zunächst mal benötigt malloc() selbst schon einiges an Speicherplatz im Codesegment, und dazu kommt noch daß vor jedem mit malloc() reservierten Speicherbereich zusätzliche Informationen abgespeichert werden.

Nehmen wir z.B. einen 32 Bit Integer, dann benötigt dieser als globale Variable genau 4 Byte Speicherplatz ... ein malloc(sizeof(uint32_t)) hingegen reserviert einen Speicherbereich der Größe "4-Byte + X", wobei X von der konkreten Implementierung des Heaps abhängig ist.

C_Classic
06.09.2010, 22:56
Noch ne Idee von mir: kann ich das ganze auch mit einer Klasse in c++ machen (gibt doch nen avr g++), die ich dann erst zu einem bestimmten zeitpunkt initialisiere?

BurningWave
06.09.2010, 23:01
Ich glaube nicht, dass es einen Compiler gibt, der für AVRs C++ compilieren kann oder?

Wenn doch, geht es, wäre sogar das beste. Falls du Hilfe brauchst frag.

C_Classic
06.09.2010, 23:33
Klar gibt es den: avr-g++
werde es dann mal wenn ich daheim bin probieren.

Dann noch ne andere Frage: kann ich Klassen mit Indexen versehen? Also: Class App(0), Class App(1), ...

Felix G
06.09.2010, 23:42
Der AVR-GCC kann auch mit C++ umgehen, allerdings nicht zu 100%. Es gibt da so einige Sprachkonstrukte die (noch?) nicht unterstützt werden.

Aber auch da stellt sich mir wieder die Frage, ob sich dadurch überhaupt RAM sparen lässt :-k



Vielleicht solltest du dich nicht so sehr auf dynamische Erzeugung von Objekten/Variablen konzentrieren, denn das ist prinzipbedingt immer mit zusätzlichem Overhead verbunden.

Möglicherweise kann man dein Problem ja auf einem anderen Weg lösen, aber um das genau sagen zu können sind weitere Informationen notwendig.
(welche Art von Daten werden wie zwischen den Funktionen übertragen?)

BurningWave
07.09.2010, 00:07
Ich finde C++ in deinem Fall ein bisschen unpassend, weil du sicher keinen RAM sparst, aber wenn es sein muss, mache eine Klasse CApp, die deine Methoden und die Variable als Member enthält. Dann hat sich dein Problem eh gelöst. Wenns sein muss könntest du deine Variable mit new im Konstruktor erzeugen (also wieder als Zeiger) und im Destruktor mit delete löschen.

C_Classic
07.09.2010, 09:41
Ich glaube es liegt hier noch ein kleines Missverständnis vor (entweder bei mir oder bei euch wegen meiner unklaren Formulierung): Die Klassen werden Nicht ALLE sofort initialisiert (ich hoffe das ist das richtige Wort; initialisieren ist doch z.b. int x=0;), sondern müssen vom "Benutzer" durch "app(x) starten" gestartet werden - und da soll dann die Klasse erstellt werden.

_R2D2: ich verstehe gerade nicht ganz wie du das meinst. Könntest mir den Aufbau der klasse an nem Beispiel erläutern?

BurningWave
07.09.2010, 12:38
Hier sind Klassen erklärt:
http://www.cplusplus.com/doc/tutorial/classes/

Klassen haben einen Konstruktor und einen Destruktor. Beim Erzeugen eines Objekts der Klasse, also z.B. wenn du eine Klasse CMyClass hast, dann erzeugst du so ein Objekt: CMyClass MyClass; wird der Konstruktor aufgerufen, der das Objekt initialisiert, z.B. Speicher reserviert. Bei Programmende wird das Objekt gelöscht. Dadurch wird automatisch der Destruktor aufgerufen, der z.B. reservierten Speicher wieder freigibt.

C_Classic
12.09.2010, 14:56
So - bin jetzt wieder daheim.

Ist es nun möglich diese Klassen mit Indexen zu versehen? Also class app(0), app(1), ...

Ich möchte diese dann später über eine Schleife aufrufen können:


for (int x=0; x<APP_CNT;x++) {
app(x).Run();
}

BurningWave
12.09.2010, 15:13
Nein ist es nicht. Du müsstest ein Array von Klassenobjekten erstellen, also quasi so: CMyClass aMyClassObjects[10]; Jetzt kannst du über aMyClassObjects[i] auf die einzelnen Objekte zugreifen, also wie bei einem normalen Array. Auf die Elemente eines Objekts greift man wie bei Strukturen mit dem Punkt (.) zu.

Warum nimmst du eigentlich keine Struktur? Das wäre doch praktischer.

C_Classic
12.09.2010, 15:37
Warum nimmst du eigentlich keine Struktur? Das wäre doch praktischer.
Weil ich noch recht neu zu C++ bin - hab bis jetzt immer C genutzt. Was ist denn da der Vorteil?

Wenn ich jetzt aber ein Array mit "CMyClass aMyClassObjects[10];" erstelle, hab ich doch 10 mal die gleiche Klasse (also Anwendung). Es sollen aber verschiedene sein.
Oder hab ich das falsch verstanden?

Oder kann ich das irgendwie mit Pointern machen?

BurningWave
12.09.2010, 16:16
Strukturen sind eindeutig aus C (kennst du das Keyword struct nicht?!)

Ich verstehe nicht ganz was zu du vorhast. Bei diesem Array hättest du 10 Objekte, diese sind von der gleichen Klasse, können aber natürlich verschiedene Werte annehmen. Das ist wie bei einem Array von integern, alles sind Integer, aber alle Elemente können unterschiedliche Werte haben. Falls du unterschiedliche Objekte (also Objekte von verschiedenen Klassen) erstellen willst, kannst du natürlich kein Array nehmen.

Am besten du suchst dir im Internet mal ein Tutorial zu Klassen oder kaufst dir gleich ein C++-Buch, wenn du es ernst meinst mit dem Lernen, das bringt dir nämlich 100x mehr.

Zu deinem Beispiel, ich nehme an, dass du eine Klasse CApplication erstellen würdest. Nehmen wir an, du hast 10 Apps, dann erzeugst du die Objekte als Array: CApplication aApps[10]; Jetzt kannst du über eine SChleife auf ein Objekt nach dem anderen zugreifen:

for(int i = 0; i < 10; i++)
aApps[i].run();

Mit Zeigern kannst du natürlich auch arbeiten, aber wozu die Sache unnötig kompliziert machen?

Erkläre am besten mal, was du genau vorhast.

C_Classic
12.09.2010, 16:53
OK - noch mal von ganz vorne.

Ich habe mehrere Klassen mit unterschiedlichem Inhalt. Also (so wie ich es mir vorstelle):


class app[0] {
void Run() {
// Z.B. Text ausgeben: Hallo Welt!
}

void Close() {
//Tschuess Welt!
}
}

class app[1] {
void Run() {
// Z.B. Text ausgeben: Hallo Universum!
}

void Close() {
//Tschuess Universum!
}
}


OK... jetzt stoß ich selbst bei der Planung auf Probleme. Aber trotzdem:
Die Klassen haben auch noch eine static Variable mit dem Namen der Anwendung.
In main wird also erst eine Schleife durchlaufen: (Syntax: CreateButton(ID, Caption);)
for (int x=0;x<2;x++) {
CreateButton(x,app[x].name);
}
Dann wird in einer unendlichen Schleife geprüft ob einer der Buttons gedrückt wird und dann ggf. die Klasse erstellt und danach Run() aus der erstellten Klasse ausgeführt. Dann gibt es noch ne Taste um die Anwendung zu beenden - also erst Close() aufgerufen und dann die Klasse zerstört.

Ich hoffe es ist jetzt klarer. Ja ich kenne struct. Jedoch verstehe ich nicht was ich in meinem Fall damit machen kann. [/code]

BurningWave
12.09.2010, 17:34
Programmierst du jetzt eigentlich für einen AVR oder für Windows??

Sorry, aber das ist 1. nicht der Sinn einer Klasse und 2. ist die Syntax total falsch.

Les mal das durch (es reicht, wenn du verstehst, zu was eine Klasse gut ist und wie sie grundlegend aufgebaut ist, den Abschnitt über Operatoren z.B. musst du nicht wissen:
http://www.rpgstudio.de:8181/scientia/C%2B%2B/Tutorial:_10._Klassen_und_Objekte

Hier noch was über statische Elemente:
http://www.rpg-studio.de:8181/scientia/C%2B%2B/Tutorial:_12._Weitere_Eigenschaften_von_Klassen

Und noch was zur Objektorientierung (warum man Klassen verwendet und zu was):
http://de.wikipedia.org/wiki/Objektorientierte_Programmierung

C_Classic
12.09.2010, 17:47
OK Danke. Ich werde dann mich mal noch etwas einarbeiten...

Und es geht schon noch um AVRs, wobei es bei diesem Thema egal ist.

MichaF
12.09.2010, 22:38
Du solltest mal genau beschreiben was du machen willst. Wenn auf einem AVR mit Klassen RAM "gespart" werden muss, ist doch schon am Konzept was verkehrt!? Wie viele Daten, und vor allem was für Daten müssen ausgetauscht werden? Wie voll ist das RAM bisher, und womit? Was soll das insgesamt mal werden?

Wie wird es überhaupt realisiert, das zur Laufzeit mehrere deiner "Apps" ausgeführt werden können? Hast du eine Art Thread-handler implementiert? Oder ist das viel mehr nach dem Motto "Der Anwender wählt etwas aus, das wird einmal ausgeführt und gut"?

Ich glaube du machst dir das Leben hier unnötig schwer.

Mehr Infos! ;)

C_Classic
14.09.2010, 14:42
Also mal das ganze Projekt:

[glow=red:a788bbb513]1. Hardware: [/glow:a788bbb513]
Die Hardware ist grundsätzlich ein Atmega644/32 und ein Datavision DG-16080 GLCD. Näheres auf http://www.youtube.com/watch?v=HRuNeVdNExo


[glow=red:a788bbb513]2. Software: [/glow:a788bbb513]
Ich habe nun vor eine einfache programmierung für dieses Board zu ermöglichen. Man soll also die Möglichkeit haben, eine Anwendung (dafür ist die Klasse) zu schreiben, die dann automatisch in einer Anwendungsliste auftaucht und das "Multitasking" (Ist eigentlich keins, sondern es soll immer zwischen den AppProc()-Funktionen der einzelnen laufenden Anwendungen gewechselt werden.Also immer nacheinander.) unterstützt.
Für dieses Prinzip soll jede Anwendung wie folgt aufgebaut sein:
AppName="NAME";
AppIcon=[Icon];
//Nun der optionale Teil mit den Variablen die das Programm benötigt. (Z.B. die GUI-Elemtente)
AppStart() Der Code der einmal am Start der Anwendung ausgeführt wird. (Also z.B. Daten aus dem EEPROM holen)
AppFocus() Wird ausgeführt wenn die Anwendung den Fokus ERHÄLT. (Also z.B. das akt. Formular aufbauen)
AppProcFocus() Wird ausgeführt, wenn die Anwendung den Fokus HAT. Z.B. zum verarbeiten von Tasteneingaben.
AppProc() Wird immer ausgeführt, sobald die Anwendung läuft. (Z.B. für ein Programm, dass einen Wert über die serielle Schnittstelle sendet)
AppClose() Wird beim schließen des Programms aufgerufen. (Z.B. zum Speichern eines EEPROM-Werts)

Und diese Apps werden zur Laufzeit gestartet und beendet.


Ich hoffe es wurde ein bisschen klarer,was ich vorhabe und wenn ihr noch Fragen habt, stellt diese bitte.
Auf jedenfall schon mal Danke für eure bisherige Hilfe!

C_Classic

BurningWave
14.09.2010, 18:16
Ok, jetzt verstehe ich, was du vorhast und auch, was du mit den Buttons gemeint hast.

Du könntest nun für alle Programme je eine Klasse schreiben, die die entsprechenden Methoden und Variablen enthält. Zusätzlich könntest du noch eine Application-Manager schreiben, die die vrschiedenen Apps verwaltet und eine Basis-Klasse, von der alle Programmklassen abgeleitet werden und die Daten enthält, die bei allen Programmen vorhanden sein müssen (also z.B. Name,...). Ansonsten könntest du mit Funktionszeigern arbeiten. Du solltest aber wirklich wissen, wie Vererbung und Funktionszeiger in C++ funktionieren und ob das alles von deinem Compiler unterstützt wird.

C_Classic
14.09.2010, 19:21
Ja, das mit den mehreren Klassen und dem App-Manager war ja auch so gemeint. Und somit sollte es doch auch möglich sein, damit Speicher zu sparen.
Jetzt ist halt die Frage, wie das geht. Wie schon gesagt, ich bin noch nicht all zu vertraut mit C++.

Das ist jetzt vielleicht etwas zu viel verlangt, aber:
Kannst du mir (oder auch jemand anderes) das Grundgerüst, also nur wie die Klassen aussehen müssten und wie ich diese dann während der Laufzeit laden kann.

Gibt es gute Links zu speziell den Themen die hierfür benötigt werden?

MfG
C_Classic

C_Classic
01.10.2010, 18:25
So. Habe mich jetzt ein paar Tage damit beschäftigt, bin jedoch zu keiner wirklichen Lösung gekommen.

Wie schaffe ich es Klassen zur Laufzeit zu erstellen, die dann von anderen Funktionen (oder wenigstens außerhalb des If-Blocks) zugreifbar sind? Gibt es wirklich keine Möglichkeit Variablen/Klassen nachträglich als public zu definieren. Also das Löschen am Ende des Blocks/Der Funktion zu verhindern.
Bei Qt z.B. habe ich die Möglichkeit, eine Klasse (also ein UI-Element) in einer Funktion zu erstellen und anschließend einer anderen Klasse hinzuzufügen. Danach ist das Element auf der Form und auch aus anderen Funktionen zugreifbar.

Mfg,
C_Classic

BurningWave
01.10.2010, 18:31
Wie wärs mit new und delete?

http://en.wikipedia.org/wiki/New_(C%2B%2B)
http://www.willemer.de/informatik/cpp/dynamic.htm

C_Classic
01.10.2010, 19:13
Könnte klappen, jedoch nicht unbedingt auf dem AVR. Ich habe gerade folgenden Codeschnipsel für new und delete:

void * operator new(size_t size)
{
return malloc(size);
}

void operator delete(void * ptr)
{
free(ptr);
}
Dieser unterstützt jedoch keine Arrays. Kann ich den Operator für Array auch noch irgendwie hinzufügen?

BurningWave
01.10.2010, 19:41
Ich habe gedacht, du benutzt einen C++ Compiler? Warum funktioniert das Schlüsselwort operator, wenn new nicht funktioniert und seit wann kann man Operatoren außerhalb von Klassen überladen?

Außerdem IST ein Array eine Art Pointer, deswegen bräuchtest du dafür keinen speziellen Operator.

Ich denke, du hast immer noch etwas grundlegend falsch verstanden. Mein Vorschlag: Entweder du kaufst dir ein C++ Buch und lernst die Sprache richtig oder du kommst mit C aus und verwendest kein C++.