Forum: PC-Programmierung Pointer auf Mehrdimensionales Array


von Student (Gast)


Lesenswert?

Hallo, ich habe ein Problem mit dem Zugriff auf ein zweidimensionales 
Array:
1
#include <stdio.h>
2
3
#define N_MAX 20
4
5
typedef int brett[N_MAX][N_MAX];
6
7
void testfunktion(int n, brett *b)
8
{
9
 int i,j;
10
11
 for( i = 0 ; i < n ; i++ )
12
  for( j = 0 ; j < n ; j++ )
13
   *b[i][j] = 0;
14
}
15
16
int main(void)
17
{
18
 brett b;
19
 int n;
20
  
21
 scanf("%d", &n);
22
 testfunktion(n, &b);
23
24
 return 0;
25
};

Entsprechender Quelltext wird zwar anstandslos kompiliert nur beim 
ausführen stürzt das Programm einfach ab. Ich hab keine Ahnung woran das 
liegen könnte. Weiß jemand woran das liegt oder noch besser eine Lösung?

Achja, ich kann nur in der Funktion werkeln, die Parameter sind 
vorgegeben.

von ... (Gast)


Lesenswert?

In der innersten Schleife den * vor dem b löschen!

von Klaus W. (mfgkw)


Lesenswert?

1
#include <stdio.h>
2
3
#define N_MAX 20
4
5
typedef int brett[N_MAX][N_MAX];
6
7
void testfunktion( int n, brett b )
8
{
9
 int i,j;
10
11
 for( i = 0 ; i < n ; i++ )
12
  for( j = 0 ; j < n ; j++ )
13
    b[i][j] = 0;
14
}
15
16
int main(void)
17
{
18
 brett b;
19
 int n;
20
  
21
 scanf("%d", &n);
22
 testfunktion(n, b);
23
24
 return 0;
25
};

von ... (Gast)


Lesenswert?

...
Und beim Aufruf von "testfunktion" in "main" kannst Du den & vor dem b 
auch weglassen.

von Student (Gast)


Lesenswert?

Dann kommt zurecht ein "incompatible types in assignment"-Fehler und es 
lässt sich nicht kompilieren.

von Klaus W. (mfgkw)


Lesenswert?

... schrieb:
> In der innersten Schleife den * vor dem b löschen!

.. und in der Parameterliste, und das & beim Aufruf.

von (prx) A. K. (prx)


Lesenswert?

Arrays werden immer per Adresse übergeben. Also:
  testfunktion(n, b);
  void testfunktion(int n, brett b)
  b[i][j] = 0;

von Daniel -. (root)


Lesenswert?

in C muss die Funktion alle Dimensionen bis auf die äusserste kennen!

sprich

int linienfeld[10];
void eindimfeld(int * pi){}

int schachfeld[8][8];
void eindimfeld(int ** pi){} <-- kacke!

int schachfeld[8][8];
void eindimfeld(int (* pi[8])){} <-- syntax frei nach Gedächtnis

wenn typedef ins Spiel kommt, so werden die Dinge nur hinter
einer Maske versteckt. Es entsteht kein neuer atomarer Typ.
(wie zB bei struct/class/union)

von Student (Gast)


Lesenswert?

Wie gesagt ich kann die Parameter von Testfunktion nicht ändern, es muss 
als Pointer ankommen.

von (prx) A. K. (prx)


Lesenswert?

Student schrieb:

> Wie gesagt ich kann die Parameter von Testfunktion nicht ändern, es muss
> als Pointer ankommen.

In
  void testfunktion(int n, brett b)
  testfunktion(n, b);
kommt es durchaus als Pointer an. Auch wenn's nicht so aussieht.

von P. S. (Gast)


Lesenswert?

1
    (*b)[i][j] = 0;

von Klaus W. (mfgkw)


Lesenswert?

oder in Langform:
1
include <stdio.h>
2
3
#define N_MAX 20
4
5
typedef int brett[N_MAX][N_MAX];
6
7
void testfunktion( int n, brett *b )
8
{
9
 int i,j;
10
11
 for( i = 0 ; i < n ; i++ )
12
  for( j = 0 ; j < n ; j++ )
13
    (*b)[i][j] = 9;
14
}
15
16
int main(void)
17
{
18
 brett b;
19
 int n, i, j;
20
  
21
 scanf("%d", &n);
22
 testfunktion(n, &b);
23
24
 return 0;
25
};

von ... (Gast)


Lesenswert?

Klaus hat natürlich völlig Recht und den zweiten fehlerhaften Stern auch 
noch gefunden.
Das jemand für Arrays typedef's benutzt, sieht man aber auch eher 
selten.

von Student (Gast)


Lesenswert?

A. K. schrieb:
> In
>   void testfunktion(int n, brett b)
>   testfunktion(n, b);
> kommt es durchaus als Pointer an. Auch wenn's nicht so aussieht.

Dann beschreibe ich es anders, im Funktionsrumpf der eigentlichen 
Funktion ist (brett * b) fest als Parameter vorgegeben und muss benutzt 
werden. genauso wird beim Aufruf im Hauptprogramm zwingend ein (&b) 
übergeben.

von Klaus W. (mfgkw)


Lesenswert?

Wenn es in der Hausaufgabe so vorgegeben ist, dann bekommen wir
das auch hin! :-)

von P. S. (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> oder in Langform:

In der Langform kann man aber stundenlang auf den Code starren und sieht 
es nicht ;-)

von Student (Gast)


Lesenswert?

Peter Stegemann schrieb:
> (*b)[i][j] = 0;

Ich danke vielmals dafür, ich bin da nen halben Tag jetzt dran!

Problem gelöst.

von Andreas F. (aferber)


Lesenswert?

Student schrieb:
> typedef int brett[N_MAX][N_MAX];
>
> void testfunktion(int n, brett *b)
[...]
>    *b[i][j] = 0;

Rangfolge der Operatoren beachten:
1
  (*b)[i][j] = 0;

Array-Indizierung bindet stärker als Pointer-Dereferenzierung, deshalb 
sind die Klammern nötig.

> };

Das Semikolon hier ist überflüssig.

Andreas

von P. S. (Gast)


Lesenswert?

Student schrieb:

> Problem gelöst.

Schritt zwei waere zu verstehen, was bei der fehlerhaften Variante 
genau passiert. :-)

von Student (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Wenn es in der Hausaufgabe so vorgegeben ist, dann bekommen wir
> das auch hin! :-)

Nicht das ich hier meine Hausaufgaben machen lassen will, die 
eigentliche Arbeit, den Algorithmus fürs Spielfeld entwickeln hab ich 
fertig, es ging wieder nur darum die verdammten sonstigen Vorgaben 
einzuhalten weil es sonst unverhältnismäßig Punktabzug gibt.

von (prx) A. K. (prx)


Lesenswert?

... schrieb:

> Das jemand für Arrays typedef's benutzt, sieht man aber auch eher
> selten.

Das ist ja nicht der Punkt. Entweder hat der Aufgabensteller nicht 
verstanden wie die Parameterübergabe in C funktioniert, oder er hat 
bewusst eine Falle gestellt, um des Elevens Nase auf genau diesen Aspekt 
zu stossen.

Wobei nun also zu hoffen ist, dass bei "Student" dieser Aspekt auch 
ankam. Sonst hat er zwar die Aufgabe richtig, versiebt aber die Prüfung 
mangels Verständnis.

von Klaus W. (mfgkw)


Lesenswert?

Dann bekommen wir hier aber ein paar von den Punkten ab, ok?

von Andreas F. (aferber)


Lesenswert?

A. K. schrieb:
> Das ist ja nicht der Punkt. Entweder hat der Aufgabensteller nicht
> verstanden wie die Parameterübergabe in C funktioniert, oder er hat
> bewusst eine Falle gestellt, um des Elevens Nase auf genau diesen Aspekt
> zu stossen.

Naja, wenn man den typedef verwendet, ist es eigentlich IMO schon guter 
Stil, hier explizit einen Pointer als Parameter zu übergeben, auch wenn 
es eigentlich "doppelt gemoppelt" ist. Nur so ist aus dem 
Funktionsprototyp alleine ohne weiteren Kontext (der ggf. zwei, drei 
Includes entfernt ist) ersichtlich, dass ein Parameter "by reference" 
übergeben wird.

Kann man sich aber drüber streiten.

Andreas

von Student (Gast)


Lesenswert?

Peter Stegemann schrieb:
> Schritt zwei waere zu verstehen, was bei der fehlerhaften Variante
> genau passiert. :-)

Denke Andreas hats bereits verraten.

Wenn der Index stärker bindet als die Dereferenzierung werde ich wohl 
bei meiner ersten Variante durch i und j die Speicheradresse verändert 
haben und dann wo ganz anders hingespeichert haben, zumindest hab ich es 
versucht.


A. K. schrieb:
>Das ist ja nicht der Punkt. Entweder hat der Aufgabensteller nicht
>verstanden wie die Parameterübergabe in C funktioniert, oder er hat
>bewusst eine Falle gestellt, um des Elevens Nase auf genau diesen Aspekt
>zu stossen.

Eigentlich sind die Grundlagenvorlesungen dafür schon einige Zeit durch, 
nur wurde uns da in der Regel freigestellt wie wir ein Problem lösen und 
das Thema Pointerdereferenzierung kaum angerissen.

Hier bei gings diesmal um die Entwicklung eines Dynamic Programming 
Algorithmus um eine ideale Zugfolge auf einem Schachbrett zu finden.
Die strikten Vorgaben sind wohl eher aus dem Willen heraus entstanden 
die zu prüfenden Stellen im Programm so übersichtlich wie Möglich zu 
halten.

>Wobei nun also zu hoffen ist, dass bei "Student" dieser Aspekt auch
>ankam. Sonst hat er zwar die Aufgabe richtig, versiebt aber die Prüfung
>mangels Verständnis.

Mach dir mal darüber keine Sorge, das Verständnis ist durchaus da, nur 
wiederspricht es dem was ich im allgemeinen so durch den Compiler jage, 
daher diesmal das Problem. Und mit Google hatte ich wohl die falschen 
Suchbegriffe, dort wurde immer nur beschrieben wie man es anders, besser 
oder einfacher machen kann.

von ??? (Gast)


Lesenswert?

Wie sieht es denn aus, wenn n > N_MAX oder n = N_MAX? Eine kleine 
Abfrage in testfunktion kann hier helfen.

???

von Student (Gast)


Lesenswert?

??? schrieb:
> Wie sieht es denn aus, wenn n > N_MAX oder n = N_MAX? Eine kleine
> Abfrage in testfunktion kann hier helfen.

Ums auf den Punkt zu bringen, du hast recht aber auf solche 
Kleinigkeiten achtet bei uns kein Mensch mehr, es werden einfach 
entsprechende Testfiles ins Programm gepiped und geschaut ob das 
rauskommt was soll. Die Grundlagen sind ansich nicht mehr Gegenstand der 
Aktuellen Vorlesung/Übung und werden darum auch in der Regel ignoriert.

von ??? (Gast)


Lesenswert?

Student schrieb:
> aber auf solche
> Kleinigkeiten achtet bei uns kein Mensch mehr, es werden einfach
> entsprechende Testfiles ins Programm gepiped und geschaut ob das
> rauskommt was soll. Die Grundlagen sind ansich nicht mehr Gegenstand der
> Aktuellen Vorlesung/Übung und werden darum auch in der Regel ignoriert.

Was Hänschen nicht lernt, lernt Hans nimmer mehr!

Feldüberschreitung, nicht initialisierte Variablen, falsche 
Dereferenzierung, ... das sind Flüchtigkeitsfehler, mit deren Suche man 
viel Zeit verbringen kann. Und wenn man das für Geld macht, sieht das 
gar nicht gut aus. Also sollten die Kleinigkeiten als 
Selbstverständlichkeit immer enthalten sein.

???

von Andreas F. (aferber)


Lesenswert?

??? schrieb:
> Feldüberschreitung, nicht initialisierte Variablen, falsche
> Dereferenzierung, ... das sind Flüchtigkeitsfehler, mit deren Suche man
> viel Zeit verbringen kann.

Und wenn man Pech hat, erfährt man von seinem Fehler erst durch ein 
Posting auf Bugtraq...

Andreas

von ??? (Gast)


Lesenswert?

Andreas Ferber schrieb:
> erfährt man von seinem Fehler erst durch ein
> Posting auf Bugtraq

und dann kann man ein kostenpflichtiges Update verkaufen.
@Student: Hast recht, viele Lücken zu lassenund und sehen was passiert 
:=)))

???

von Student (Gast)


Lesenswert?

??? schrieb:
> Was Hänschen nicht lernt, lernt Hans nimmer mehr!
>
> Feldüberschreitung, nicht initialisierte Variablen, falsche
> Dereferenzierung, ... das sind Flüchtigkeitsfehler, mit deren Suche man
> viel Zeit verbringen kann. Und wenn man das für Geld macht, sieht das
> gar nicht gut aus. Also sollten die Kleinigkeiten als
> Selbstverständlichkeit immer enthalten sein.

Bei mir rennst du da offene Türen ein, nur wird das maximal, wenn man 
die Aufgabensteller direkt drauf anspricht, mit einem "Ja kann man 
machen, ist aber eigentlich egal" abgetan. Da der gesamte Workload aber 
recht ordentlich ist, verkneift man sich irgendwann die Teile zu machen 
die eh nicht interessieren (Bereichsprüfungen, 
Speicher-/Laufzeitoptimierungen, Dokumentation, hübsche Ausgabe, -Wall 
Kompilierung, etc). Ich mach das Ganze ja auch leider nicht um was dabei 
zu lernen sondern nur für die Extrapunkte die auf die Klausur 
angerechnet werden, sogesehen war das heute aussergewöhnlich und ist 
auch sofort in mein C-Buch gewandert weil ich DAS irgendwann sicher 
nochmal brauchen werde.

von ??? (Gast)


Lesenswert?

Student schrieb:
> wenn man
> die Aufgabensteller direkt drauf anspricht, mit einem "Ja kann man
> machen, ist aber eigentlich egal" abgetan.

set (Sarkasmus);
Bachelor?
clear (Sarkasmus);

???

von Student (Gast)


Lesenswert?

Nicht das ihr mich falsch versteht, wenn ich selber was programmiere bau 
ich das so idiot-proof wie möglich, war selber schon überrascht wie 
viele Leute es gibt die sowas nötig haben. Nur für die wöchentlichen 
Aufgaben wo es keinen interessiert hab ich da nicht genug Zeit und 
Motivation, was aber wohl auf Gegenseitigkeit beruht.

von Student (Gast)


Lesenswert?

??? schrieb:
> set (Sarkasmus);
> Bachelor?
> clear (Sarkasmus);

Ja, heute kann man ja nicht mehr richtig studieren, zumindest nicht in 
Westdeutschland.

PS: Der Sarkasmus-Mode steht bei mir auf auto.

von Klaus W. (mfgkw)


Lesenswert?

> Ja, heute kann man ja nicht mehr richtig studieren, zumindest nicht in
> Westdeutschland.

War das früher besser?
Das einzige, was ich im Studium in Richtung Informatik etc. geniessen
durfte, war eine Fortran-Vorlesung.
Dazu gab es Übungen, die bestanden werden mussten.
Das sah folgendermaßen aus:
- Es wurde eine Aufgabe vorgegeben
- Man hat dann ein passendes Programm geschrieben und die eigene
  Matrikelnummer irgendwo in den Jobkarten (ja, das war auf Lochkarten)
  hinterlegt zur Anerkennung
- Wenn das Programm dann vom Operator eingelegt wurde, hat ein
  automatisches Prüfprogramm die Ausgabe mit der (uns unbekannten)
  Musterlösung verglichen, Zeichen für Zeichen.
- Man hat genau dann bestanden, wenn alle Zeichen der Ausgabe richtig
  waren.
  Wie der Quelltext aussah, hat niemanden interessiert - der durfte
  beliebig schlecht aussehen. Dafür war es wichtig, die Ausgabe
  wie gefordert zu formatieren, ein Leerzeichen zuviel war
  absolutes KO-Kriterium.

von ??? (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> War das früher besser?

Off Topic!!!

Der Sarkasmus Mode war ON, der pointer ist inkompatibel ;=)

???

von Klaus W. (mfgkw)


Lesenswert?

??? In Fortran gibt es keine Pointer...

von ??? (Gast)


Lesenswert?

Ok Klaus, ich caste es zum longint und schon passt es :=)))

???

von Karl H. (kbuchegg)


Lesenswert?

Student schrieb:

> rauskommt was soll. Die Grundlagen sind ansich nicht mehr Gegenstand der
> Aktuellen Vorlesung/Übung und werden darum auch in der Regel ignoriert.

Und dann wundert man sich, warum die praktisch arbeitenden Leute in den 
Firmen draussen so eine schlechte Meinung von den ganzen 
Dozenten/Übungsleitern und ganz speziell den Professoren auf den Unis 
haben.
Bei vielen ist es wirklich so, dass man den Professoren am besten erst 
mal ein paar Nachhilfestunden anbieten sollte, ehe man sie auf Studenten 
loslässt.

von Student (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> War das früher besser?

Denke das war es, auch wenn ich Früher (TM) nicht dabei war. Ich glaube 
der eigentliche Vorteil am alten System war das es nicht so verschult 
war und man sich Zeit nehmen konnte um sich mit der Materie zu 
beschäftigen.
Heute läuft es nur auf stupides runterreissen der immergleichen Inhalte 
hinaus, wobei zumindest bei uns ein 4-jähriges Diplom in einen 
3-jährigen Bachelor verwandelt wurde und die Inhalte immernoch gleich 
aussehen, es wird halt nur alles schneller erzählt.
Nur sobald man rechts und links vom "Hauptpfad" genauer hinschaut ist da 
garnichts mehr zu finden, die Leute wollen alle nur irgendwie durch die 
Prüfungen kommen und es gibt nur bei sehr wenigen Motivation das Ganze 
auch zu verstehen.
Ich für meinen Teil habe z.B. durch die Postings von Karl Heinz 
Buchegger wesentlich mehr über Programmierung in C gelernt als in den 
entsprechenden Grundlagenvorlesungen, nur andererseits sehe ich das 
Projekt Regelstudienzeit auch nicht ganz so eng und hab darum auch 1-2 
Extrasemester eingeplant.

von Student (Gast)


Lesenswert?

Wenn man vom Teufel spricht...

von Karl H. (kbuchegg)


Lesenswert?

Student schrieb:

> Ich für meinen Teil habe z.B. durch die Postings von Karl Heinz
> Buchegger wesentlich mehr über Programmierung in C gelernt

Brauchst aber nicht glauben, dass ich das auf der Uni gelernt habe.
Mit einer einzigen Ausnahme waren meine Praktika nämlich auch nach dem 
oben beschriebenen Muster(n) gestrickt.

Das einzige worüber ich heute so einigernmassen froh bin, auch wenn es 
damals lästig war:
Meine ersten beiden Semester waren noch eingeschränkte Accounts auf dem 
Großrechner (ha, der Begriff alleine :-)
Wir hatten unsere Praktikumsbeispiele alle 2 Wochen abzugeben und nur 1 
(in Worten: einen) Compilerlauf täglich (eigentlich nächtlich), private 
PC gabs noch nicht. Da wurde es lebensnotwendig die syntaktischen 
Feinheiten des ; in der jeweiligen Sprache möglichst schnell im Schlaf 
zu beherrschen. Sonst kam man mit der Zeit nicht hin. 5 oder 6 
Compilerläufe nur um Syntaxfehler zu beheben waren bei den späteren 
Übungen im Semester einfach nicht mehr drinnen.

Heut jag ich den Compiler drüber, damit mir der raussucht, welche 
Variablen ich noch nicht definiert habe :-)

von Sven (Gast)


Lesenswert?

[offtopic]

Student schrieb:
> Nicht das ihr mich falsch versteht, wenn ich selber was programmiere bau
> ich das so idiot-proof wie möglich, war selber schon überrascht wie
> viele Leute es gibt die sowas nötig haben.

Da fällt mir direkt ein schickes Zitat ein:
1
Das grösste Problem von Leuten, die versuchen, etwas absolut idiotensicherers zu konstruieren, 
2
ist, dass sie den Einfallsreichtum von absoluten Idioten unterschätzen.

Ich glaub es ist von Douglas Adams.

(btw.: 42)

[/offtopic]

Meiner Meinung nach sollte man gerade solche Sachen nie nie nie nie 
[...] nie unterschätzen. Das sind genau die Lücken, die später mal dazu 
führen, dass böse Menschen sich an deiner Software vergreifen und sich 
Zugang zu Dingen verschaffen, zu denen sie sich besser keinen Zugang 
verschaffen können sollten.


Karl heinz Buchegger schrieb:
> Wir hatten unsere Praktikumsbeispiele alle 2 Wochen abzugeben und nur 1
> (in Worten: einen) Compilerlauf täglich

Krasse Sache. Kann ich mir mit meinen zarten 25 garnicht vorstellen. Ich 
weiß nur noch, damals ;-) da mussten wir an nem Mikrocontroller die 
Befehle per Taster einprogrammieren... (oh, ich werd schon wieder 
offtopic)

von Jauhen L. (jles)


Lesenswert?

Klaus Wachtler schrieb:
> ??? In Fortran gibt es keine Pointer...

...obwohl alle Parameter standardmäßig per Referenz (d.h. als Pointers) 
übergeben werden :) Also gibt es in Fortran überall Pointers, man sieht 
sie einfach nicht ;)

P.S. Die Lochkarten und Fortran sind auch meine alten Bekannte aus 
Studiumzeiten. Die Ergebnisprüfung war aber nicht so hart gewesen.

von Klaus W. (mfgkw)


Lesenswert?

Karl heinz Buchegger schrieb:
> Wir hatten unsere Praktikumsbeispiele alle 2 Wochen abzugeben und nur 1
> (in Worten: einen) Compilerlauf täglich (eigentlich nächtlich), private
> PC gabs noch nicht.

Abgeben konnten wir unsere Stapel beliebig, eingelesen wurden sie
mehrfach täglich.
Der Flaschenhals waren aber die Kartenstanzer: um Quelltexte zu
editieren, musste man da ran. Und dafür gab es Reservierungspläne,
in die man sich eintragen musste. Leider waren die regelmässig
für die nächsten Tage schon voll.
Da kommt man dann schon mal auf die Idee, kleine Änderungen
von Hand zu machen: Löcher kann man zukleben, neue mit dem
Skalpell schneiden. Wenn man das sauber macht, funktionieren
die sogar.

von jua (Gast)


Lesenswert?

Dazu muss man allerdings sagen, dass viele der Studenten an der Uni zum 
ersten mal richtig selber programmieren. Sie sind dann oft mit Pointern 
und Funktionen oder Klassikern wie "=" vs "==" schon hinreichend 
ausgelastet... da sollte man es vielleicht nicht übertreiben mit den 
Inhalten.
Die Schwierigkeiten am Anfang sind auch völlig normal -- ich denke, 
jeder erinnert sich noch an seine Anfänge im Programmieren, und von Null 
auf C in einem Semester (welches ja noch zig andere Vorlesungen enthält) 
ist schon eine Menge.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.