2 Anfänger Fragen: Array und Dev C++

tobee hat gesagt.:
Code:
char count(const char* a)
{
  return sizeof(a) / sizeof(a[0]);
}
Das ist meine Funktion wo ich die Array Größe ermittel.
Irgend etwas ist aber noch falsch?
Ich sagte ja bereits das du diese Methode nur bei statischen Arrays benutzen kannst.

Wenn du einen Zeiger an eine Funktion übergibst ist und bleibt das nur ein Zeiger. Dieser hat keine Struktur mehr und die Information die der Compiler von einem statischen Array hat sind nicht verhanden. Der Zeiger hat eine konstante Größe - auf einem 32bit System normalerweise 4 Byte. Da es ein Zeiger auf char ist, ist die Größe von a[0] immer 1 Byte. Das heißt die Funktion liefert immer 4 zurück.

Wenn du ein dynamisches Array benutzt (was erst zur Laufzeit erstellt wird), dann mußt du dir die Größe selbst merken, da der sizeof Operator nur zur Kompilierzeit verwendet werden kann.

Gruß
 
deepthroat hat gesagt.:
Ja, Zeiger sind erstmal ein etwas kompliziertes Konzept.

Zeiger sind Variablen die Adressen speichern. Punkt.

Mit dem Adressoperator & kann man sich die Adresse von Variablen besorgen.

Bsp:
C:
int x = 5;

int* y = &x;
x ist eine Integervariable die mit dem Wert 5 initialisiert wurde. y ist eine Variable vom Typ Zeiger auf int. Mit dem &-Operator wurde die Adresse der Variablen bzw. genauer die Adresse an der der Wert der Variablen steht ermittelt; und dann an y zugewiesen.

y speichert jetzt also die Adresse an der der Wert der Variablen x steht.

Um den Wert der Variablen x zu verändern kann man den Zeiger dereferenzieren:
C:
*y = 10;
Das Sternchen wird hier zum Dereferenzieren benutzt. Das bedeutet es wird nicht der Wert von y geändert, sondern da wo y hinzeigt wird der Wert 10 gespeichert. Die Variable x hat also jetzt den Wert 10, der Wert von y ist immer noch unverändert.

Nützlich werden die Zeiger wenn man dynamische Datentypen benutzt oder beim Funktionsaufruf wo Ausgabeparameter verwendet werden.

Gruß

Also wäre dann x = 10 und y wäre immer noch 5. Oder?
Aber eins hab ich immer noch nicht verstanden.
Was ist der Sinn von Zeigern. Programm läuft schneller? Mehr Übersicht? :confused: :confused: :confused:

Tobee
 
tobee hat gesagt.:
Also wäre dann x = 10 und y wäre immer noch 5. Oder?
Nein. y speichert immer noch die Adresse von x. Man kann sich die Adresse ausgeben lassen:
C:
printf("%p\n", y);
tobee hat gesagt.:
Aber eins hab ich immer noch nicht verstanden.
Was ist der Sinn von Zeigern. Programm läuft schneller? Mehr Übersicht? :confused: :confused: :confused:
Einen Vorteil gibt's z.B. bei der Übergabe an Funktionen. Hat man eine Variable die viel Speicher belegt und übergibt diese als Parameter an eine Funktion, wird der Wert der Variablen kopiert wenn die Funktion aufgerufen wird. Das beansprucht Rechenzeit und auch Speicher - was nicht unbedingt notwendig ist. Übergibt man nur die Adresse der Variablen, hat man sich diesen Aufwand gespart. Hinzu kommt noch, das man den Wert der Variablen von der man die Adresse hat auch innerhalb der aufgerufenen Funktion ändern kann:
C:
void func_a (int x) {
  x = 5;
}

void func_b (int* x) {
  *x = 5;
}

int main() {
  int z = 25;
  func_a(z);
  // z ist immer noch 25.

  func_b(&z);
  // z ist jetzt 5.
}
Gruß
 
deepthroat hat gesagt.:
Nein. y speichert immer noch die Adresse von x. Man kann sich die Adresse ausgeben lassen:
C:
printf("%p\n", y);

Einen Vorteil gibt's z.B. bei der Übergabe an Funktionen. Hat man eine Variable die viel Speicher belegt und übergibt diese als Parameter an eine Funktion, wird der Wert der Variablen kopiert wenn die Funktion aufgerufen wird. Das beansprucht Rechenzeit und auch Speicher - was nicht unbedingt notwendig ist. Übergibt man nur die Adresse der Variablen, hat man sich diesen Aufwand gespart. Hinzu kommt noch, das man den Wert der Variablen von der man die Adresse hat auch innerhalb der aufgerufenen Funktion ändern kann:
C:
void func_a (int x) {
  x = 5;
}

void func_b (int* x) {
  *x = 5;
}

int main() {
  int z = 25;
  func_a(z);
  // z ist immer noch 25.

  func_b(&z);
  // z ist jetzt 5.
}
Gruß

Das heißt.
void func_b (int* x) {
Sagt der Funktion es kommt ein Zeiger als Parameter.

x wird dereferenziert.

Erstellt einen Zeiger


Ist das so richtig?
Tobee
 
Danke. Da les ich wochenlang in C++ Bücher check nicht was Zeiger sind und du erklärst es mir in ~ 4 Stunden. Super ;)
 
Zuletzt bearbeitet:
tobee hat gesagt.:
Danke. Da les ich wochenlang in C++ Bücher check nicht was Zeiger sind und du erklärst es mir in ~ 4 Stunden. Super ;)
Also bei mir hat es noch ein bisschen länger gedauert bis ich es wirklich verstanden hatte. Da hilft nur üben. :)

tobee hat gesagt.:
Noch was:
Ich habe ein Funktion die leider noch nicht funktioniert:
Code:
char count(char theArray)
{
char r = sizeof(theArray) / sizeof(theArray[0]);
return r;
}
Du übergibst da ein einzelnes Zeichen als Parameter an die Funktion. Da dürfte sich der Compiler ziemlich beschweren wenn du den Index-Operator (die eckigen Klammern) anwenden willst.

Du kannst den sizeof Operator wirklich nur verwenden um die Größe eines Arrays zu bestimmen wenn du direkt eine (statische) Array-Variable vorliegen hast:
C:
int x[] = { 1, 2, 3 };

int count = sizeof(x) / sizeof(x[0]);
Der Compiler hat in dem Fall die Information darüber das x eine Array-Variable ist, wie groß x ist und wie groß jedes einzelne Element von x ist. Wenn du x an eine Funktion als Zeiger übergibst, ist diese Information nicht mehr vorhanden. Die Äquivalenz gilt eben nur in eine Richtung: ein Array ist ein Zeiger, aber nicht jeder Zeiger ist automatisch auch ein Array.

Um Arrays in Funktionen verarbeiten zu können, muss immer (wie z.B. der main Funktion selbst) die Anzahl der Elemente bzw. die Größe des Arrays als Parameter übergeben werden. Oder man benutzt ein speziellen Wert um das Ende des Arrays zu markieren - wie z.B. bei Strings, da markiert ein NUL Zeichen das Ende eines Strings (ist nichts anderes als ein char-Array).

Du könntest count höchstens so schreiben:
C:
int count(int sz, char arr[]) {
  return sz / sizeof(arr[0]);
}

char array[] = { 'a', 'b', 'c' };
int size = count (sizeof(array), array);

Du könntest allerdings auch ein Makro verwenden:
C:
#define COUNT(x) (sizeof(x) / sizeof(x[0]))

int size = COUNT(array);
Das Makro wird expandiert bevor der C/C++ Compiler den Code verarbeitet und es ist im Grunde dasselbe wenn du gleich die sizeof Berechnung hinschreibst.

Gruß
 
Ok, eine "dumme" Frage habe ich noch Lager ;)

Code:
int count(int sz, char *arr[])
{
  return sz / sizeof(arr[0]);
}

Würde das hier einen Unterschied machen, wie zu dem hier:
Code:
int count(int sz, char arr[])
{
  return sz / sizeof(arr[0]);
}

Die Funktion erwartet ja einen Zeiger?
Und wenn keiner kommt?


Tobee
 
Ok. Also erstmal ist ja der Parameter arr bei den Funktionen von einem unterschiedlichen Typ. Das erste ist ein Array von Zeigern auf char und das zweite nur ein Array von char.

Da müssen dann wieder die Typen beim Aufruf passen. Das sollte der Compiler dann auch bemängeln. Einen Unterschied macht es insofern, das die Elemente der Arrays eine andere Größe haben. Ein char ist immer 1 Byte groß und ein Zeiger ist bei 32bit Systemen meist 4 Byte groß.

Übergeben wird allerdings immer ein Zeiger. Wird ein falscher Typ übergeben der nicht mit dem Typ des Parameters kompatibel ist stimmt die Berechnung nicht mehr. Übergibt man der ersten Funktion statt des erwarteten char*-Arrays z.B. ein char-Array ist die Berechnung natürlich falsch.

C ist da sehr nachlässig und gibt dem Programmierer sehr viel Freiheiten. Deshalb sollte man immer alle Warnungsmeldungen des Compilers anzeigen lassen und dann die Ursachen beseitigen. /edit: C++ ist da übrigens sehr viel strenger und dieser Code würde nicht akzeptiert werden.

Gruß
 
Zuletzt bearbeitet:
Ich habe gerade ein kleines Programm geschrieben und ein Kollege hat gesagt wenn ich den Bildschirm "leeren" möchte muss ich nur cls eingeben.
Das funktioniert aber leider nicht.
Ich hab es schon so
Code:
cls;
und so
Code:
cls();
probiert. Oder war das eine falsche Information?

Tobee
 
Zurück