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!
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?
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;
...
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;
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...
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);