Hallo, hab hier folgendes Problem: beim comilieren der folgenden Zeile tritt fogende Fehlermeldung auf: *(u08)comm_tab[mid].ptr=parametervalue_intern; " operand of "*" must be a pointer" was sagt mir das?...und wie kann ich das Problem lösen? danke
Was machst Du denn da? Was ist u08? Was ist "comm_tab[mid].ptr"? Ein Zeiger, nehme ich an?! Soll dieser in einen Zeiger auf u08 gecastet werden? Wenn ja, muß es heißen (*u08)... Dann könntest Du wohl auch einfach schreiben (*u08)comm_tab[mid]->ptr = ... oder ((*u08)comm_tab[mid]).ptr = .... (Ich bin mir hier nicht sicher, ob die äußeren Klammern nötig sind, sie machen jedenfalls klar, was man meint. Besser ist wohl die Schreibweise mit '->'.) Gruß, Michael
u08 ist Typ char ich hab redefiniert: u08 ist char, u16 ist unsigned int...etc comm_tab[mid].ptr ist ein zeiger auf parameter in meine tabelle, der zeiger muss auf den Typ, der der Paremeter in der Tabelle hat gecastet werden...wie geht das?
Na dann mußt Du mit (*int) oder eben mit (*s16) casten. Also: Sei ptr irgend ein Zeiger (auf irgend einen Typ), dann machst Du daraus mit (*int)ptr oder (*s16)ptr einen Zeiger auf int oder auf s16!
versuch "((*s16)comm_tab[mid]).ptr=(s16)parametervalue_intern;" Bis morgen!
Um da durchzublicken müßte ich größere Teile Deines Quellcodes sehen. Insbesondere die Deklaration der beteiligten Typen und Variablen. Gruß, Michael
Hallo NG, jetzt will ich auch mal zur Verwirrung beitragen: (*s16)comm_tab[mid].ptr=(s16)parametervalue_intern; Arry oder Struct oder ? comm_tab[mid] du "castest" Dein Struct (oder was auch immer) (*s16)comm_tab[mid] zu einem INT-Pointer (damit kannst du die Adresse auslesen an der Dein Struct (?) im Ram steht ... Zugreifen würde ich nicht auf ein Element - böse falle ... Und warum willst du die Adresse an einen INT übergeben ? Ich nutze dafür WORD oder DWORD ... Versuch mal: comm_tab[mid].ptr = ¶metervalue_intern; (& zeigt auf die Adresse von parametervalue_intern) Vorrausgesetzt das comm_tab[mid].ptr ein POINTER ist (*irgentwas) sollte das gehen ... Lg CHW
@Christian: >Arry oder Struct oder ? >comm_tab[mid] Weder Array, noch struct ;), sondern ein Array von structs %) Hier mal mein kleines Demonstrationsprogrämmchen, lauffähig auf dem PC mit MinGW/Cygwin: --8<-- #include <stdlib.h> #include <stdio.h> typedef signed short s16; typedef struct ptrlist_s { unsigned char *foo; void *ptr; } ptrlist_t; ptrlist_t comm_tab[128]; int main(void) { s16 val[128] = {0xAA}; int i = 0; for(i = 0; i < 128; i++) { comm_tab[i].ptr = &val[i]; printf("%d: member ptr @%p, content = 0x%02X\n", i, comm_tab[i].ptr, *(s16 *)comm_tab[i].ptr); } return 0; } -->8-- Einfach mal alles durchdenken und vielleicht auch ausprobieren... Falls da noch Probleme sind, einfach nochmal fragen!
> ((*s16)comm_tab[mid]).ptr=(s16)parametervalue_intern;
Eben nicht!
Sondern:
(*s16)(comm_tab[mid].ptr)=parametervalue_intern;
Der Pointer soll in einen Pointer auf s16 umgewandelt werden, nicht das
Struct, in dem der Pointer sitzt.
Allerdings wundert es mich doch sehr, daß ein Compiler die
Typenumwandlung enger binden läßt als den Structselektor. Wann könnte
das jemals sinnvoll sein?
Evtl. hat das damit zu tun: typedef struct test_s { unsigned char byte0; unsigned char byte1; unsigned char byte2; unsigned char byte3; unsigned char byte4; unsigned char byte5; unsigned char byte6; unsigned char byte7; } test_t; unsigned char bytearray[8] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; [..] printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", ((test_t *)bytearray)->byte0, ((test_t *)bytearray)->byte1, ((test_t *)bytearray)->byte2, ((test_t *)bytearray)->byte3, ((test_t *)bytearray)->byte4, ((test_t *)bytearray)->byte5, ((test_t *)bytearray)->byte6, ((test_t *)bytearray)->byte7); [..]
Guten Morgen so langsam blick ich gar nichts mehr und bin total verwirrt Wenn ich: (*s16)(comm_tab[mid].ptr)=parametervalue_intern; mache kommt folgende Fehlermeldung: error: type name is not allowed
Dann mach es doch so, wie ich das oben beschrieben habe! Ich erklärs nochmal: *(s16 *)comm_tab[x].ptr | | | | | | | `- Member "ptr", typ "void *" | | `------------- Struktur "comm_tab", typ "ptrlist_t" | `------------------- Cast auf "s16 *", pointer auf s16 `--------------------- Dereferenzierung In einen "void *" passen alle anderen Pointer ebenfalls rein. Deswegen brauchst Du bei der Zuweisung comm_tab[x].ptr = &val; nicht zu casten. Das "&" sorgt dafür, daß nicht der Inhalt von val, sondern die Adresse von val an dieser Stelle "erscheint".
Ich bitte noch einmal darum, dass Du mehr von Deinem Quellcode postest! Mindestens die Stellen, an denen die beteiligten Typen und Variablen Deklariert werden.
Seht ihr eigentlich alle den Fipptehler bei samuel nicht? (*s16)foobar; Was soll das bewirken? Es benötigt kein fitzelchen Code mehr, ich habe die Lösung bereits erläutert!
@samuel:
Also, einfach wäre Du postest alle relevanten Codezeilen. Aber egal:
> (*s16)(comm_tab[mid].ptr)=parametervalue_intern;
Es fehlt vermutlich (vermutlich, weil ich Deinen Source nicht kenne und
nur raten kann), noch ein Sternchen. Also:
*(*s16)(comm_tab[mid].ptr)=parametervalue_intern;
Erklärung:
Willst Du an die Speicherstelle etwas schreiben, wo ein Pointer
hinzeigt, so musst Du diesen Pointer dereferenzieren. Dazu wird der
Prefix '*' verwendet. Beispiel:
int variable; /* Speicherplatz für 'variable* */
int * zeiger = &variable; /* Zeiger auf 'variable' */
variable = 123; /* Direkte Zuweisung */
*zeiger = 456; /* 'zeiger' derefenzieren, dann zuweisen
*/
Du musst zwei Versionen des Sternchens unterscheiden. In der
Deklaration benutzt Du es um einen Pointer zu deklarieren, und in einer
Expression (Zuweisung) benutzt Du das Sternchen um einen Pointer zu
dereferenzieren.
Folgends ist übriges alles das gleiche. In jedem der drei Versionen
wird an die Speicherstelle auf die 'zeiger' zeigt, der Wert '123'
hineingeschrieben.
*zeiger = 123;
zeiger[0] = 123;
*(zeiger + 0) = 123;
Und noch ein paar einfachere Beispiele:
int a;
int b;
int * p;
a = 123; /* 'a' enthält nun '123' */
p = &a; /* 'p' enthält nun die Adresse von 'a' */
b = *p; /* 'p' wird dereferenziert, und 'a' in 'b' kopiert
*/
p = &b; /* 'p' zeigt nun auf 'b' */
*p = 456; /* 'b' enthält nun '456' */
Und noch ein kleiner Tip: Ich mach mir für das Casten immer Makros,
damit ich nicht so viele Klammern schreiben muss und damit die Sache
schön übersichtlich wird:
typedef unsigned char uint8;
#define CAST(t, v) ((t)(v))
#define UINT8(v) CAST(uint8, (v))
#define UINT8_p(v) CAST(uint8 *, (v))
a = (uint8)(b); /* ohne Makro, unübersichtlich, fehleranfällig */
a = UINT8(b); /* mit Makro, viel freundlicher */
Und noch ein letzter Tip: Anstatt eigene Typedefs zu machen, verwendet
doch "inttypes.h". Das ist C99 und ihr habt die ganzen Typen:
#include "inttypes.h"
uint8_t a;
int8_t b;
uint16_t c;
int16_t d;
...
AAAAAAARRRRRRRRRRGGGGGGGGLLLLLLLLLL!!!!
> *(*s16)(comm_tab[mid].ptr)=parametervalue_intern;
Ist natürlich Bullshit!!!! Richtig ist:
*(s16 *)(comm_tab[mid].ptr)=parametervalue_intern;
@OldBug:
Danke, danke, danke, danke, danke, danke....
Also mit folgendem Code will ich den Wert von parametervalue_intern an den zugehörigen Parameter z.B. "parameter1" in der Tabelle zuweisen, dabei klappt eben die Zuweisung in der switch Anweisung nicht, jedenfalls hab ich den Wert nach den Operationen nicht in der variablen z.B. parameter1 stehen.woran liegt das? s16 parameter1; s32 parameter2; //etc... //struct typedef struct{ char *name; u08 type; void *ptr; }comm_struct; //zugehörige tabelle const comm_struct comm_tab[] = { // command table {"parameter1",TYPS16,¶meter1}, {"parameter2",TYPS16,¶meter2}, //etc..... } switch (comm_tab[mid].type) { case TYPS16: comm_tab[mid].ptr=¶metervalue_intern; break; case TYPU16: comm_tab[mid].ptr=¶metervalue_intern; break; case TYPS32: comm_tab[mid].ptr=¶metervalue_intern; break; case TYPU32: comm_tab[mid].ptr=¶metervalue_intern; break;
Habe es gerade ausprobiert: *(s16 *)(comm_tab[mid].ptr)=parametervalue_intern; ist genau richtig.... juhu es funktioniert.....vielen Dank an alle!!!
Aha!
Also, mit:
> comm_tab[mid].ptr=¶metervalue_intern;
änderst Du den Pointer selbst. D.h. nach dieser Zuweisung zeigt
comm_tab[mid].ptr auf die Adress von 'parametervalue_intern'.
Was Du aber möchtest ist, dass der Wert von 'parametervalue_intern'
an die Adresse geschrieben wird, auf die 'comm_tab[mid].ptr' zeigt.
Das geht so:
*(s16 *)(comm_tab[mid].ptr) = parametervalue_intern;
Oha! Jetzt wird mir erst das ganze Ausmaß dieser Geschichte bewusst! Es will nicht nur den Wert in die Variable schreiben, auf die x.ptr zeigt, sondern auch noch den richtigen Typen dafür casten. In "Pseudo-Code" also sowas: *(x.typ *)x.ptr = newval; ...da muss ich nochmal ein bißchen grübeln...
Aha, deswegen das switch-statement: case TYPS16: *(s16 *)comm_tab[mid].ptr = (s16)parametervalue_intern; break; case TYPU16: *(u16 *)comm_tab[mid].ptr = (u16)parametervalue_intern; break; [..]
Es gibt immer mal wieder Überraschungen beim Casten, denn ich habe beispielsweise trotz 32-Bit-Int auf dem PC feststellen müßen, dass int32_t aus stdint.h nicht gleich int ist! Deshalb benutze ich häufig ein cast-Makro: // for assignment with type conversion, e. g. char *cp; const char *ccp; mc_ASSIGN(cp, cpp); #define mc_ASSIGN(a, b) a=(typeof(a))b Es gibt auch allgemeinere Cast-Makros: // Cast any object to nearly any type via pointers. Works also with struct and union but only with objects. // You are responsible for correct alignment, endianess and representation!!! #define mc_CAST(new_type,old_object) (*((new_type *)(&(old_object)))) Damit kann man auch Funktionen casten, was z. B. für qsort und bsearch sinnvoll ist. Ausgeschrieben sieht das z. B. so aus: qsort(a, 10, sizeof(int), (int (*) (const void *, const void *)) intcompare);
#define mc_CAST(new_type,old_object) (*((new_type *)(&(old_object)))) Sowas ist schön und gut, aber sollte höchstens dann verwendet werden, wenn man auch ganz genau weiß, was das bewirkt. Einer der Vorzüge von Ansi-C gegenüber dem alten nahezu typüberprüfungsfreien K&R-C ist ja die Typüberprüfung - und die wird mit solchen Macros komplett ausgehebelt. Wenn ich den Thread hier (und andere vom gleichen Autor angestoßene) rekapituliere, gewinne ich den Eindruck, daß es hier nicht hilfreich ist, solche Brachialwerkzeuge anzuwenden. Zwar spuckt der Compiler beim Gebrauch derartiger Konstrukte keine Fehlermeldungen mehr aus, aber es kann halt auch etliches in die Hose gehen, was dem C-Anfänger den Zugang zur Sprache weiter erschweren wird. Compilerfehlermeldungen und -Warnungen sollte man durch korrekt formulierten Code beseitigen, aber nicht durch Umgehen der Typüberprüfung oder sonstigen unsauberen Tricks. Das kann man - vielleicht - dann tun, wenn man ganz genau weiß, was man da macht, aber wirklich nicht, wenn man gerade die ersten Klimmzüge mit C macht.
Ok, das letztere der Makros benutze ich nur sehr selten und meist schreibe ich auch wegen der Lesbarkeit die Casts meist aus, beispielsweise so: qsort(a, 10, sizeof(int), (int (*) (const void *, const void *)) intcompare); pthread_create (&pro, NULL, (void *(*)(void *)) func_timeout, NULL);
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.