Forum: Compiler & IDEs Array und pointer


von Marian (Gast)


Lesenswert?

Hallo Forum,

ich hoffe die Frage ist jetzt nicht zu banal aber ich bin langsam aber
sicher am verzweifeln. Kurz zur Erklärung: Ich möchte mir ein Array mit
256 Werten anlegen und dann im Hauptprogramm einmal pro
Schleifendurchlauf einen Wert ins Array schreiben und dann wenn das
Array voll ist, dieses mit printf ausgeben. Ich dachte mit das
folgendermaßen:

int16_t fr[256]; //Mein Array
char *pa;        //Der zeiger auf mein Array(Index)
pa = fr;         //Den zeiger beim 1.Element des Arrays beginnen
lassen

int main(void)
{
  *pa = aktuellerWert;
  *pa++;
  if (pa==256) printf("fr[i]=%i",fr);
}
Leider schlägt es schon bei der Deklaration des Arrays fehl.Folgende
Fehlermeldungen kommen:
main.c:35: warning: type defaults to `int' in declaration of `pa'
main.c:35: error: conflicting types for 'pa'
main.c:34: error: previous declaration of 'pa' was here
main.c:35: warning: initialization makes integer from pointer without a
cast
main.c:35: warning: data definition has no type or storage class
main.c:290: error: invalid type argument of `unary *'
main.c:291: error: invalid type argument of `unary *'
main.c:292: warning: int format, pointer arg (arg 2)
main.c:338: error: invalid type argument of `unary *'
main.c:339: error: invalid type argument of `unary *'
main.c:340: warning: int format, pointer arg (arg 2)

Leider kann ich mit diese Meldungen nicht viel anfangen. Laut C und C++
Kursen deklariere ich mein Array richtig aber wieso will das AVRstudio
(gcc) dieses nicht annehmen? Was mache ich falsch?

von FrankW (Gast)


Lesenswert?

Was als erstes gleich mal auffällt :

int16_t fr[256]; //Du machst Ein Array mit 16 INT Werten
char *pa;        //Der Zeiger soll aber auf "char" zeigen
pa = fr;         //Jetzt willst Du einen "char" Pointer auf "int16"
zeigen lassen.

Deshalb jammert der Compiler

int16_t fr[256]; //Mein Array
int16_t *pa;     //Der zeiger auf mein Array(Index)
pa = fr;         //Den zeiger beim 1.Element des Arrays beginnen

sollte gehen.

Gruss
FrankW

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du deklarierst ein int16-Array, möchtest aber mit einem char-Zeiger
darauf zugreifen.

Desweiteren ist pa ein Zeiger und kein Index, daher kannst Du den nicht
mit einem konstanten Wert wie 256 vergleichen.

Ansonsten ist Dein Code nicht gerade sinnvoll in main() aufgehoben, so,
wie Du das formuliert hast, wird das exakt einmal aufgerufen.

Alternative:
1
int16_t fr[256]; //Mein Array
2
char pa = 0;         //Index
3
4
5
6
void wert_in_array_packen(int16_t aktuellerwert)
7
{
8
  int i;
9
10
  fr[pa] = aktuellerWert;
11
  pa++;
12
13
  if (pa == 256) 
14
  {
15
    for (i = 0; i < 256; i++)
16
      printf("fr[i]=%i", fr[i]);
17
    pa = 0;
18
  }
19
}

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Erst mal der hier:

>(pa==256)

Wie soll das denn gehen?
der grösstmögliche Wert von pa ist 255.
Du müsstest also abfragen if (pa==0)

Dann willst einen char-Pointer auf ein Int-Array zeigen lassen.
Entweder benutzt du pa als Index von 0 bis 255 oder deklarierst ihn als
int-pointer.
Vielleicht solltest du mal einen Blick in das Buch von Dennis und Brian
werfen, und dir das Kapitel über Pointer und Felder angucken. Ab der
2.Auflage ist die deutsche Version auch nicht mehr so wirr
geschrieben...

von Marian (Gast)


Lesenswert?

Ja das ist mir auch gerade so aufgefallen aber das war es nicht. Auch
wenn beide gleich definiert sind meckert er rum. Habe nun die Zeile:
pa=fr;

rausgenommen und siehe da, es funktioniert. Aber wieso stört ihn das?
Und wie soll ich nun sonst den Pointer am Anfang des Arrays starten
lassen?
Um die Werte dem Array zuzuführen mache ich es nun so:

*pa=WERTaktuell;
*pa++;
if (*pa==256) printf("fr[i]=%i",fr);

Nun kommt diese Fehlermeldung:

main.c:291: warning: int format, pointer arg (arg 2)

Aber das Array und der Pointer sind doch nun Integer, also warum ist
das falsch?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

printf("fr[i]=%i",*fr);

von FrankW (Gast)


Lesenswert?

.... und den Rest verstehe ich auch nicht

int main(void)
{
  *pa = aktuellerWert;
  *pa++;   // Meinst Du nicht eher    pa++ statt *pa++ ?
           // Du willst doch den Pointer erhöhen,
           // nicht den Wert, auf den der Pointer zeigt



  if (pa==256) printf("fr[i]=%i",fr);
  // Dass pa jemals 256 wird ist sehr sehr sehr unwahrscheinlich :-)
  // pa ist ein Pointer, der irgenwo in den Speicher deines RAM's
  // Zeigt. Mit sicherheit wird Dein Array nicht bei Speicherplatz
  // 0 anfangen.
  // Also - z.B. parallel Zähler mitlaufen lassen und den abfragen.
  // Und wo das "i" fuer fr[i] herkommt, das können wir nur raten.

}

von Stefan (Gast)


Lesenswert?

Beschaffe dir ein C-Buch oder C-Tutorial und lese es durch. Dir fehlen
die Grundlagen der Sprache.

Denk daran: Du hast nur eine gewisse Anzahl Fragen frei und hier
verplemperst du einige davon. Später, wenn du die wirklich kniffeligen
Fragen hast, antwortet dir keiner mehr.
1
if ( *pa == 256 ) 
2
   printf( "fr[i]=%i", fr[i] );

von FrankW (Gast)


Lesenswert?

> // Und wo das "i" fuer fr[i] herkommt, das können wir nur raten.
Ups - sorry. Da ist ja nur ein Text.

von Karl heinz B. (kbucheg)


Lesenswert?

> if (*pa==256) printf("fr[i]=%i",fr);
>
> Nun kommt diese Fehlermeldung:
>
> main.c:291: warning: int format, pointer arg (arg 2)
>
> Aber das Array und der Pointer sind doch nun Integer, also warum
> ist das falsch?

Weder das Array noch der Pointer sind Integer.
Das Array ist ein Array von Integer. Und der Pointer ist ein
Pointer auf Integer.

Im printf gibst du aber mit dem %i (warum eigentlich %i, tuts
%d nicht auch?) an, dass die einen Integer übergibst. fr ist
aber kein Integer, fr ist ein komplettes Array von Integern
und das ist nun mal was anderes.
Wie man ein Array ausgeben kann, hat Rufus weiter oben schon
gezeigt.

von Karl heinz B. (kbucheg)


Lesenswert?

> aber ich bin langsam aber sicher am verzweifeln

Das musst du nicht. Kauf dir ein Buch.
Der Klassiker von Kernighan & Ritchie ist immer noch eines
der Standardlehrbücher über C.

Eine Programmiersprache ohne ausreichende Unterlagen lernen
zu wollen ist so wie wenn ich ohne entsprechende Unterlagen
und Schulung den Leitstand eines Kernkraftwerkes übernehmen
sollte. Erst recht dann, wenn ich neben der neuen Programmier-
sprache auch noch gleichzeitig das Programmieren an sich lernen
muss.

von Stefan K. (_sk_)


Lesenswert?

Warum muss es unbedingt ein Pointer sein?
So wie es aussieht, kennst Du Dich mit denen noch nicht so gut aus.
Nimm einen Index-Zähler, das ist für den Anfang einfacher zu
durchschauen:
1
int16_t fr[256]; //Mein Array
2
uint16_t index = 0;
3
4
int main(void)
5
{
6
  while(1){
7
8
    fr[index] = aktuellerWert;
9
    index++;
10
    if (index == 256){
11
      index = 0;                    // Nullsetzen fürs nächste Mal!
12
      for(n=0; n<256; n++){         // alle 256 Werte ausgeben:
13
        printf("fr[i]=%i\n",fr[n]); // immer nur 1 Wert aus dem
14
Array
15
      }
16
    }
17
18
  } // end of while(1)
19
}   // end of main

Wenn Du es mit Index kannst, dann versuche es mit Pointern!

Gruß, Stefan

von Stefan K. (_sk_)


Lesenswert?

ups peinlich .. hat ja Rufus schon alles mal geschrieben ...

Gruß, Stefan

von Marian (Gast)


Lesenswert?

Tja ich weiß gar nicht wo ich anfangen soll.
Also ich weiß selbst das mir die C-Grundlagen fehlen, aber ich versuche
ja auch gerade diese mir anzueignen. Im Moment bin ich halt dabei Arrays
und Pointer zu üben. Ich habe zwar kein C-Buch aber dafür nutze ich
sämtliche Online Kurse die ich gefunden habe um zu üben.

Das mit dem pa==256 war ein Schussligkeitsfehler...den hätte ich später
bestimmt auch selbst noch gefunden aber danke für den Hinweis.

>>Ansonsten ist Dein Code nicht gerade sinnvoll in main() aufgehoben,
so,
wie Du das formuliert hast, wird das exakt einmal aufgerufen.

Ja das ist mir auch klar, das war nur so als Beispiel angedacht wie ich
das dann halt in der for-Schleife for(;;) machen wollte. Sollte nicht
einfach so in der main stehen, sondern halt im for(;;){}.

Eins habt ihr mir aber noch nicht erklärt:
>>Habe nun die Zeile:
pa=fr;
rausgenommen und siehe da, es funktioniert. Aber wieso stört ihn das?
Und wie soll ich nun sonst den Pointer am Anfang des Arrays starten
lassen?

Kann mir das noch einer erklären?

Ich danke auf jeden Fall allen die mir gerade geholfen haben...ein
Sorry an alle, die das lesen des Beitrages genervt hat aber ich schrieb
ja am Anfang, dass es warhscheinlich ein sehr banales Thema ist.

von Karl heinz B. (kbucheg)


Lesenswert?

> Ich habe zwar kein C-Buch aber dafür nutze ich
> sämtliche Online Kurse die ich gefunden habe um zu üben.

Vergiss die Online Kurse.
Die Online Kurse kommen selten über 20 Seiten hinaus.
Selbst das lausigste C-Buch hat aber über 100 Seiten.
Und jetzt frag dich mal warum.

> Eins habt ihr mir aber noch nicht erklärt:
> >>Habe nun die Zeile:
> pa=fr;
> rausgenommen und siehe da, es funktioniert. Aber wieso stört ihn
> das?

Doch das wurde schon erklärt:

fr ist ein Array von int !
pa hast du aber als Pointer auf char definiert. Das heist also
wenn du einen gültigen Pointer Wert in pa stehen hast, dann führt
dich dieser Pointer Wert bei der Dereferenzierung zu einem char.
Daher kann die Zuweisung nicht gehen, denn wie gesagt, fr ist
ja ein Array von int:
  char != int

von Karl heinz B. (kbucheg)


Lesenswert?

Noch was:

> siehe da, es funktioniert

Der Compiler akzeptiert es. Das heist aber noch lange nicht
das es funktioniert. Der Compiler überprüft nur, ob dein
Programm den Schreibregeln (der sog. Syntax) der Programmier-
sprache entspricht. Ob dein Programm logisch richtig ist,
kümmert ihn einen Pfurz.

Das ist so, wie wenn ich sage, dass in der deutschen Sprache
für einen Satz gilt:
 Subjekt Verb Objekt

Das heist der Satz:
Die Feuerwehr  löscht   den Brand

ist ein gültiger deutscher Satz. Aber

Die Feuerwehr    weht    das Kino

ist auch ein deutscher Satz. Er entspricht genauso obiger Regel.
Nur macht er halt keinen Sinn.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Weil's noch keiner geschrieben hat (glaub' ich),

int16_t fr[256];
char *pa;
pa = fr;

Das steht vor deinem main() und damit außerhalb jeglicher
Funktion.  Dort sind aber nur Deklarationen und Definitionen
zugelassen, keine Zuweisungen.  Was (mit Warnungen, wegen der
Typinkompatibilität) geht ist:

int16_t fr[256];
char *pa = fr;

Damit ändert sich die Zuweisung in eine Intialisierung.

von Marian (Gast)


Lesenswert?

Aha und wie sagt man stattdessen, dass der Pointer auf das 1. Element
des Arrays zeigt und nicht irgendwo in den Speicher?

Auf jeden Fall ist die Sache mit dem Index für mich erstmal sehr
interessant. Das habe ich auch sofort verstanden, denn so dachte ich
mir das auch mit dem Pointer.

Naja ich werde mir jetzt mal nen C-Buch besorgen gehen. Was ist denn
Sinnvoller? Das empfohlene von Kernighan & Ritchie für C oder eines für
C++?

von Marian (Gast)


Lesenswert?

Ups gleichzeitig abgesendet!

Danke Jörg, genau das wollte ich auch noch wissen.

von Karl heinz B. (kbucheg)


Lesenswert?

C und C++ sind verschiedene Sprachen.
Du willst C lernen, ergo ...

> Aha und wie sagt man stattdessen, dass der Pointer auf das 1.
> Element des Arrays zeigt und nicht irgendwo in den Speicher?

Das tust du automatisch bei der Zuweisung der Adresse. Wenn
ein Array ohne einen Indexausdruck verwendet wird, dann ist
das in den meisten Fällen gleichbedeutend mit der Adresse
des ersten Arrayelementes im Speicher:

 int fr[100];
 int* pa = &fr;

Hier ist pa ein Zeiger auf int. fr ist ein Array von int. Also
passt das auch zusammen.

von inoffizieller WM-Rahul (Gast)


Lesenswert?

C++-Bücher setzen in der Regel C-Kenntnisse vorraus.

Falls Du es immer noch nicht verstanden haben solltest:
pa ist ein Pointer auf eine Variable von type char.
Dein Array ist aber ein int-Feld.
Das verträgt sich nicht.

so solltes es funktionieren:

int *pa;
int fr[256];

pa = fr;

jetzt kann man die einzelnen Feldeinträge mit pa++ "adressieren" und
mit *pa ausgeben.

von Karl heinz B. (kbucheg)


Lesenswert?

Da hat bei mir der Tippfehlerteufel zugeschlagen:

> int fr[100];
> int* pa = &fr;

muss heissen:

int fr[100];
int* pa = fr;

oder aber, weil gleichbedeutend:

int fr[100];
int* pa = & fr[0];

von Karl heinz B. (kbucheg)


Lesenswert?

> C++-Bücher setzen in der Regel C-Kenntnisse vorraus.

Um solche Bücher sollte man aber in der Regel einen Bogen machen.

von Marian (Gast)


Lesenswert?

>>int fr[100];
>>int* pa = fr;

>>oder aber, weil gleichbedeutend:

>>int fr[100];
>>int* pa = & fr[0];

Tja auf die Idee, dem Pointer gleich bei der Initialiserung die Adresse
zuzuweisen bin ich noch nicht gekommen. Das war ja das Problem was Jörg
schon erklärt hat.

Mit den Büchern bin ich jetzt allerdings etwas verwirrt. Wenn ich den
GCC nutze programiere ich doch in C++ oder? Welches sollte ich mir denn
nun aneigenen?

von Karl heinz B. (kbucheg)


Lesenswert?

Der gcc ist ein 'Kombi-Compiler'. Der kann C und C++
kompilieren (*). Das hat historische Ursachen, da sich C++
aus C entwickelt hat.

Wird der gcc im C++ Modus benutzt, dann heist er meist g++

Das heist: Ob du C oder C++ kompilierst hängt davon ab, welche
Parameter beim Aufruf mitgegeben werden. Aber meistens ist es
auf einem µC C.


(*) so war das mal. Mittlerweile hat sich das weiterentwickelt.
Unter gcc versteht man heutzutage eigentlich einen Compiler,
der durch Austausch von Modulen im Compiler eine ganze Reihe von
Sprachen übersetzen kann.

von Marian (Gast)


Lesenswert?

Ok danke :)

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.