Linker Operand soll L-Wert sein/Strukturen

Ok, danke jetzt hab ich den header nach stdio geschrieben aber es kommen diese Fehler:
Fehler 2 fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
Fehler 1 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_main" in Funktion "___tmainCRTStartup". MSVCRTD.lib

Zeile steht nicht dabei wo passiert.
 
EDIT: Ok, ich hab vergessen die .c-files und .h-files ins Projekt "hinzuzufügen" unter Projekt-Explorer etc.

Auf jedenfall funktionierts danke^^!
 
Zuletzt bearbeitet:
Du solltest das Header-File stdio.h auch in das Header-File für deine Strukturen-Definition includieren.

Also noch mal als Erklärung die Sache mit den Pointern:

Wenn du eine definierte Struktur personendaten hast, kannst du ein Objekt auf zweierlei Arten dafür erstellen.

Variante 1 - Objekt-Variable auf den Stack

C:
personendaten p;

Damit sorgst du dafür, das bereits beim Starten deines Programms Speicher für das Objekt auf dem Stack reserviert wird. Du musst dich nicht darum kümmern, dass der Speicher dafür wieder aufgeräumt wird. Sobald der Scope (der Bereich in dem die Objekt-Variable definiert wurde) verlassen wird, ist die Variable nicht mehr gültig. Beim Verlassen des Programms wird der Speicher dafür implizit freigegeben.

Diese Variante ist für Anfänger die einfachere, da man sich eben nicht um die Speicherverwaltung kümmern muss. Es wird aber eines Tages ein Anwendungsfall kommen, wo du mit dieser Variante alleine nicht mehr weiter kommst. Beispiel: Du musst eine Objekt-Variable erstellen, die größer als der Stack ist, der normalerweise für deinen Compiler und dein Betriebssystem definiert ist.

Zugriff auf Elemente der Struktur:

C:
// Da es sich nicht um einen Zeiger handelt, darfst du auch nicht den Referenz-Operator verwenden:

strncpy(p.name, "Hans", sizeof(p.name)-1); // Sicherheitshalber mal die Länge beschränken

Variante 2 - Objekt-Variable auf den Heap

C:
personendaten *p;

Hier wird lediglich ein Zeiger erstellen. Dieser Zeiger zeigt auf irgendeine Stelle im Speicher. Besser wäre es hier schon mal, den Zeiger mit NULL zu initialisieren, da der Zeiger einen undefinierten Zustand hat.

Möchtest du einen Zeiger tatsächlich als Datenspeicher verwenden, musst du dafür Speicher anfordern. Es gibt Funktionen, die das von sich aus erledigen (z.B. strdup()). was du auf jeden Fall dann machen musst, ist den Speicher wieder freigeben, sobald er nicht mehr benötigt wird. Wie das geht, habe ich weiter oben schon gezeigt.

Zugriff auf die Elemente der Struktur über den Zeiger:

C:
// Da es sich um einen Zeiger handelt, musst du auch den Referenz-Operator verwenden:

strncpy(p->name, "Hans", sizeof(p.name)-1); // Sicherheitshalber mal die Länge beschränken


Fazit:

Das sind absolute C-Grundlagen, du solltest den Unterschied erkennen und verstehen. Mein Gefühl sagt mir, das du Zeiger noch nicht verstanden hast.
 
Danke!

Aber eins is mir noch nicht klar...:

Saftmeister schrieb:

C++:
// Expliziter Pointer-Cast weil malloc() einen void* zurück gibt
personendaten p = (personendaten*)malloc( sizeof( personendaten ) )

Was macht jetzt das (personendaten*) vor malloc genau? Warum?

Hier ein kurzer Programm-Ausschnitt:
C++:
complex* c_read_file(char filename[], int* len)
{
  FILE *inFile=NULL;
  complex *arrayValues=NULL;
  complex *actVal = NULL;
  int n=0;
  
  inFile=fopen(filename,"r");
  if (inFile != NULL) 
  {
    arrayValues=(double *)malloc(sizeof(complex)* *len);//* 
    if (arrayValues != NULL)
    {
      actVal=arrayValues;
      for(n=0; n<*len; n++)
      {
				fscanf(inFile,"%lf,%lf",&actVal->real,&actVal->imag);
				actVal++;
      }
      fclose(inFile);
    }
    else
    {
      printf("Memory allocation failure for Data of File %s !\n",filename);
    }
  }
  else
  {
    printf("File %s could not be opened!\n",filename);
  }
	return(arrayValues);
}

*hier dieser double-cast beim malloc - Warum? Und sizeof(complex) ermittelt halt die Bytes... in dem Fall steht in der Sturktur complex double real und double imag --> also 16 Bytes? Dadurch das arrayValues ein Pointer auf complex ist der Stern *? ja und len ist die Länge(also die Zeilen-Anzahl) des text-files. Es steht in jeder Zeile eine double-Zahl.

Gruß
 
malloc bekommt, wie du ja weißt, nur die Byteanzahl, die es besorgen soll.
Wenn das 16 ist, können das zB. 16 chars (je 1 Byte), oder 2 doubles (je 8 Byte) sein.
Und weil malloc nicht weiß, welche Variablenart das wird (und sich dafür auch überhaupt nicht interessiert), liefert es nur die Adresse. Kein char* oder double*, sondern einheitlich
(void*: Adresse von unbestimmter Variablenart).

Wenn man dieses void* dann einem double* oÄ. zuweist, kann (nur kann) das
je nach Compiler eine Warnung bringen. Das Programm funktioniert trotzdem,
aber die Warnung ist lästig. Deswegen der Cast, um die zu verhindern.
 
Danke dir.

C++:
arrayValues=(double *)malloc(sizeof(complex)* *len);

EDIT:
Das ist verwirrend... der Stern ist erst nach der ) und beim len ist der stern eh normal vorm len.
Was macht der Stern den nach ')'?
 
Zuletzt bearbeitet:
Stimmt.
Je nach Compiler können es auch mal mehr als 16 Byte sein,
aber das hat auf den Code keine Auswirkungen.
Kein Grund zum Sorgenmachen,

edit: Der erste Stern ist das math. Multiplizieren,
der zweite wegen dem Pointer, um nicht die Adresse, sondern den Wert selbst zu bekommen.
 
Expliziter Cast bedeutet, das wir dem Compiler mitteilen, das wir ihn zwingen, dort einen bestimmten Typen zu verwenden.

Ein Void-Pointer ist für den Compiler etwas anderes als ein Pointer auf eine Struktur. Da du als L-Wert einen Pointer auf eine Struktur hast, als R-Wert von malloc() aber ein Void-Pointer zurück kommt, zwingen wir (casten) zum Datentypen Pointer auf Struktur.

Prinzipiell ist es bei einem Void-Pointer egal, ob man ihn explizit castet oder nicht. Der Compiler wird sich darum kümmern, dass dies implizit (also ohne Zwang durch den Programmierer) geschieht. Es ist aber sauberer, und wenn man nach ISO-89 compiliert (wenn ich mich richtig erinnere) wird der Code dadurch auch besser zu verstehen, denn:

In ISO-89 (man vergebe mir bitte, wenn ich das falsch in Erinnerung habe) müssen die Variablen vor dem eigentlichen Programm-Code definiert werden. Das sieht das bspw. so aus, wie du es in deinem letzten Post gemacht hast. Erst kommen die Variablen, dann der logische Code. Wenn man eine Latte von Variablen definiert hat, und anschließend ein paar Zeilen Code kommen, und später erst die Speicher-Allokation, dann muss man immer im Sourcecode nach oben zur Variablen-Definition scrollen, um zu prüfen, auf welchen Typ denn nun der Pointer eigentlich zeigt.

Solltest du keinen expliziten Cast durchführen, bekommst du bim Compilen eine Warnung.

Hier habe ich noch mal eine Seite raus gesucht, in der die Einzelheiten erklärt werden: http://www.willemer.de/informatik/cpp/pointer.htm
 

Neue Beiträge

Zurück