C-Frage

Gast #295842
Hallo C-Spezialisten,

ich muß von C++ nach C absteigen, mit Grausen...

kann ich in C struct eine "Memberfunktion" definieren?

Beispiel, bei dem der Metrowerks meckert:

typedef enum _tTaskState_ {
  TS_IDLE  = 0,
  TS_BUSY = 1
} tTaskState;

typedef enum _tTaskError_ {
  TE_NONE   = 0,
  TE_ERROR = 1
} tTaskError;

typedef struct _tTask_ {
  tTaskState   m_eState;
  tTaskError  m_eError;

  void Initialize(void);
} tTask;

tTask Task1;
tTask Task2;

in main wollte ich dann das C++ like machen:

...
Task1.Initialize();
...

Geht das in Hardcore C nicht? Was muß ich ändern um solche Ausdrücke
zu erhalten:

Task1.Initialize();


Vielen Dank für eure Hilfe!


Manfred
Gast
In C benutzt du keine Memberfunktionen :-)

Immer schön Daten und Code trennen, z.B. so:

typedef struct _tTask_ {
  tTaskState m_eState;
  tTaskError m_eError;
} tTask;

void Initialize_tTask(tTask* pTask);  // evntl. mit Rückgabewert?

Alles andere ist IMHO kein C sondern irgendein Mischmasch...
Persönliche Seite
Hi

man kann schon eine Art "Member-Funktionen" für Strukturen verwenden.
Nur muss man dann eben alles was der C++ Compiler macht von Hand machen.
 Nicht umsonst waren die ersten verfügbaren C++ Compiler reine
Textparser die aus dem C++ Sourcecode C Code erzeugt haben welcher dann
von einem normalen C-Compiler übersetzt wurden konnte.

Es braucht halt sehr viel Disziplin wenn man this-Zeiger, vtable, Kon-
und Destruktoraufrufe usw. händisch verwalten muss.

C++ ist eine Programmiersprache für Männer. C ist eine für Helden :-)

Matthias
Persönliche Seite
Etwas ähnliches kann man in C so realisieren:
1
typedef struct test_s {
2
  int a;
3
  int b;
4
  
5
  void (*Initialize)(void);  
6
} test_t;
7

8
void
9
init(void)
10
{
11
  printf("Init!\n");
12
}
13

14
test_t test1 = {0, 0, &init};
15

16
int
17
main(void)
18
{
19
  test1.Initialize();
20

21
  return 0;
22
}

Ob das Deinen Vorstellungen nahe kommt, kann ich nicht sagen, da ich
von C++ so gut wie überhaupt keine Ahnung habe...
Persönliche Seite
Hi

@Patrick
Das ist nicht das was Manfred erreichen möchte. Es fehlt der
init-Funktion nämlich der Bezug zur Instanz der Struktur von der aus
sie aufgerufen wurde. Wenn dann müßte man das etwa so realisieren:
1
typedef struct test_s {
2
  int a;
3
  int b;
4
  
5
  void (*Initialize)(void *);  
6
  void (*Foo)(void *);
7
  void (*Bar)(void *);
8
} test_t;
9

10
void init(void * p)
11
{
12
  test_t * this = p;
13

14
  this->a = 1;
15
  this->b = 4;
16
}
17

18
void foo(void * p)
19
{
20
  test_t * this = p;
21
  //Do something
22
}
23

24
void bar(void * p)
25
{
26
  test_t * this = p;
27
  //Do something else
28
}
29

30
test_t test1 = {0, 0, init, foo, bar};
31

32
int main(void)
33
{
34
  test1.Initialize(&test1);
35
  test1.Foo(&test1);
36
  test1.Bar(&test1);
37

38
  return 0;
39
}

Nichts anderes macht ein C++-Compiler. Jede Methode hat einen
zusätzlichen, versteckten Parameter. Und das ist eben der this-Zeiger.

Matthias
Persönliche Seite
Hi

Konstruktoren und Destruktoren haben (erstmal) nichts mit malloc und
free (die man in C++ eh nicht benutzt -> new, delete) zu tun. Ein
Konstruktor wird beim Erzeugen (ob jetzt per new, als globales Objekt
oder auf dem Stack spielt dabei keine Rolle) eines Objekts aufgerufen
und ein Destruktor beim Zerstören eines Objekts. Das wars dann auch
schon (insofern keine Vererbung hinzukommt).

Matthias
Persönliche Seite
Hi

manuell für jede Instanz einer Struktur einmal aufrufen. Konstruktor
unmittelbar nach der Erzeugung der Struktur, Destruktor unmittelbar vor
deren Zerstörung. Ein Konstruktor ist nichts anderes (zumindest nicht
viel) als eine Member-Methode (so wie oben z.B. Initialize) bei der der
C++ Compiler dafür sorgt das sie zur richtigen Zeit aufgerufen wird.

Matthias
Gast
Hi,

was mache ich denn wenn ich das struct nicht als Reference also auf dem
Stack habe. In meinem Fall habe ich lediglich einen Zeiger auf das
Struct.

struct a_ThreeAddressCode {
  IMCodeType         mOperation; // type of operation
  IMCode             mRegister1; // goal register or label
  IMCode             mRegister2; // first operant
  IMCode             mRegister3; // second operant
  ThreeAddressCode*  mNext;
  char*              (*convertOperation) (void *);
};

ich will dann über ne liste iterieren und halt

  tac->convertOperation(tac);

aufrufen.

convertOperation wandelt lediglich ein enum in einen char* um.
Gast
Im Moment mache ich es so:

void writeProgramCode() {
        ThreeAddressCode root = {  tac_root->mOperation,
                                   tac_root->mRegister1,

                                   tac_root->mRegister2,
                                   tac_root->mRegister3,
                                   tac_root->mNext,
                                   convertOperation };

        ThreeAddressCode* temp = &root;

        while (temp){
          fprintf(stdout, "%s\n", root.convertOperation(temp));
        temp = root->mNext;
        }
}

Die Lösung ist aber nicht grad elegant, wenn ich dahingegen:

        while (temp){
          fprintf(stdout, "%s\n",
(*(temp->convertOperation))(temp));
        temp = root->mNext;
        }

nehme, dann iteriert er mit nur über das erste Element, und dann ist
Schluss.

BTW. Kennt sich jemand mit Registerallokation aus?

Ich brauche einen Algorithmus, der dies für einen RISC Processor mit 32
Register, wobei R31 ein Zeiger auf den Hauptspeicher ist, durchführt.

MfG

Manfred

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 20 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.