PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pointer - endlich verstehen



Mauro
31.05.2010, 09:45
Hallo zusammen!

Ich habe schon Pointer benutzt ohne sie je zu verstehen. Bisher habe ich solange rumgebastelt, bis alle Fehler-/Warnmeldungen weg waren. Jetzt habe ich aber ein Array und da hilft alles Basteln nichts mehr :-)

Meine Funktion:
int m3dmg_getOrientationMatrix( int16_t *M ) {
//UART Buffer auslesen
for ( int i=1 ; i <= 18 ; i=i+2 ) {
*M [i] = ( (int16_t) responseBuffer[i] << 8 | (int16_t) responseBuffer[i+1] );
}
return *M;
}

Meine Main:
int main(void) {
int16_t M[9];
...
int itest2=m3dmg_getOrientationMatrix( &M );
...
}

Error:
*M [i] =.....: invalid type argument of 'unary *' (have 'int16_t')
Warning:
int itest2=m3dmg_getOrientationMatrix( &M )...: passing argument 1 of 'm3dmg_getOrientationMatrix' from incompatible pointer type

M ist meine Transformationsmatrix, die ich in einer Unterfunktion einlese. Jetzt will ich das noch in meine Main weitergeben. Neben den Fehlermeldungen habe ich * und & mit denen ich nichts anfangen kann. Habe den starken Verdacht, dass ich gar nicht weiß was ich tue und das mache ich besonders gut :-)
Mein schickes C-Buch ist nicht für meine Gehirnwindungen gemacht worden.

Für Anmerkungen zum Thema und Lösungsvorschläge bin ich sehr dankbar.

Liebe Grüße!
emm

BurningWave
31.05.2010, 11:05
Also, mal ganz von vorne:
Ein Pointer ist ein Zeiger, der auf eine bestimmte Speicherstelle zeigt, man kann ihn neu zuweisen, also ihn auf eine andere Speicherstelle verweisen lassen und die Daten, die sich an der Speicherstelle, auf die er zeigt, befinden, manipulieren.

Hier mal ein Beispiel:


int i = 50; //i = 50
int *p = &i; //Zeiger p erstellen (*-Operator für Zeigerdekleration) und ihm die Adresse von i zuweisen (& ist der Adressoperator, mit ihm kommt man an die Adresse von i)
*p = 20; //i = 20, *p = 20 - *-Operator ist notwendig, da man dem Zeiger sonst eine neue Adresse zuweisen würde
int ii = 30;
p = &ii; //*p = 30, ii = 30 - dem Zeiger eine neue Adresse (die von ii) zuweisen
p = NULL //den Zeiger, wenn er nicht mehr verwendet wird, auf NULL setzen

char acEinArray[256]; //Array mit 256 char-Elementen, Zugriff über z.B. acEinArray[50] = ...
char *p = acEinArray; //Zeiger p erstellen, der auf das Array zeigt (kein &-Operator, da acEinArray ohne []-Operator schon die Adresse ist!)
//p zeigt auf acEinArray[0], kann mit *p ausgelesen werden
p++; //p zeigt jetzt auf acEinArray[1]


So jetzt zu deinem Code:


*M [i] = ( (int16_t) responseBuffer[i] << 8 | (int16_t) responseBuffer[i+1] );
muss heißen:

M[i] = ( (int16_t) responseBuffer[i] << 8 | (int16_t) responseBuffer[i+1] );
da der []-Operator den Zeiger schon dereferenziert.

Und lass bei return *M; den *-Operator weg, damit die Adresse zurückgegeben wird und schreibe statt:

int itest2=m3dmg_getOrientationMatrix( &M );

int16_t *pitest2=m3dmg_getOrientationMatrix( &M );

Mauro
01.06.2010, 08:59
Danke für die Erklärung, die Geschichte mit den Arrays ist ja quasi ein bisschen anders mit der Dereferenzierung.
Habe das ganze mal gemacht wie geschrieben und bekomme nun noch Warnings:
warning: passing argument 1 of 'm3dmg_getOrientationMatrix' from incompatible pointer type
warning: initialization makes pointer from integer without a cast
int *pitest2=m3dmg_getOrientationMatrix( &M ); <-- muss Pointer gleiches Format wir M haben?
warning: unused variable 'pitest2' <-- ist mir egal, will ja nur M

Es scheint nicht besser geworden zu sein :-( der error ist weg :-)

sast
01.06.2010, 11:50
zum einen machst du immer noch den Fehler mit &M einen Pointer auf den Int16-Pointer zu setzen, anstatt du einfach M benutzt. Der Arraybezeichner ist ja bereits ein Pointer auf die erste Stelle im Array und zum anderen ist deine Funktion sicher immer noch als int bekannt gegeben du wirst jetzt aber versuchen einen Pointer zurückzugeben. Falls ich falsch liege, wäre es sinnvoll, wenn du den geänderten Code mal posten würdest.

sast

Mauro
01.06.2010, 12:37
Meine Funktion:
int m3dmg_getOrientationMatrix( int16_t M ) { <-- so ist auch der Header
//UART Buffer auslesen
for ( int i=1 ; i <= 18 ; i=i+2 ) {
M [i] = ( (int16_t) responseBuffer[i] << 8 | (int16_t) responseBuffer[i+1] );
}
return M;
}

Meine Main:
int main(void) {
int16_t M[9];
...
int16_t *pitest2=m3dmg_getOrientationMatrix( M );
...
}

Error:
M[i]=...: error: subscripted value is neither array nor pointer

Das ist der aktuelle Stand.

BurningWave
01.06.2010, 12:51
Benutz doch bitte die Code-Tags, das ist so unübersichtlich sonst.



int m3dmg_getOrientationMatrix( int16_t M ) { <-- so ist auch der Header

Der Header ist falsch. Es muss


int16_t* m3dmg_getOrientationMatrix( int16_t *M ) {
heißen.

Mauro
01.06.2010, 14:53
Vielen Dank!
Jetzt läuft es.

Und ich habe gelernt so ein Code-Tag zu nehmen :-)
Grüße,
eMM

BurningWave
01.06.2010, 15:12
So jetzt habe ich dafür noch zwei Fragen:
1. Funtionieren auch Referenzen?
2. kann man in C mittels int *pi = new int; Speicher reservieren oder geht das nur in C++? Funktionen wie malloc() funktionieren ja meines Wissens nach nicht, oder?

Mauro
01.06.2010, 15:15
Erst lief es, besser: keine Warnings mehr, nun sind sie wieder da :-)

Also Header ist jetzt:

// Get Gyro Orientation Matrix
int16_t* m3dmg_getOrientationMatrix( int16_t *M );

Main:

int16_t *pitest2=m3dmg_getOrientationMatrix( &M );

Funktion:

int16_t* m3dmg_getOrientationMatrix( int16_t *M ) {
//UART auslesen
for ( int i=1 ; i <= 18 ; i=i+2 ) {
// x = cast MSB um 8 Bits nach links verschieben und cast LSB, dann schreiben
M[i] = ( (int16_t) responseBuffer[i] << 8 | (int16_t) responseBuffer[i+1] );
}

return M;
}

Warnings:

int16_t *pitest2=m3dmg_getOrientationMatrix( &M );
: warning: passing argument 1 of 'm3dmg_getOrientationMatrix' from incompatible pointer type
und

int16_t *pitest2=m3dmg_getOrientationMatrix( &M );: warning: unused variable 'pitest2'

Mauro
01.06.2010, 15:24
Selber doof :-)
(M) statt (&M)

Und was mache ich mit meinem Zeiger *pitest2 damit er nicht mehr unused ist? Den brauche ich ja nicht mehr, habe ja mein M?

sast
01.06.2010, 15:25
@mauro warum verwendest du beim Funktionsaufruf immer noch &M. Darauf hatte ich dich doch schon hingewiesen?

@R2D2 warum soll malloc in C nicht funtionieren. Das new in C funktioniert wäre mir allerdings neu.

Edit: dann lass doch die Variable pitest2 einfach weg und benutze dein M nach dem Funktionsaufruf

BurningWave
01.06.2010, 15:30
Und was mache ich mit meinem Zeiger *pitest2 damit er nicht mehr unused ist? Den brauche ich ja nicht mehr, habe ja mein M?

Du kannst entweder nur die Funktion aufrufen und den Rückgabewert nicht beachten oder du kannst den Zeiger benutzen.



int16_t *pitest2=m3dmg_getOrientationMatrix( &M );
& weglassen!!