Forum: Mikrocontroller und Digitale Elektronik Probleme beim casten


von samuel (Gast)


Lesenswert?

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

von MSE (Gast)


Lesenswert?

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

von samuel (Gast)


Lesenswert?

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?

von MSE (Gast)


Lesenswert?

Auf was (welchen Typ) soll er denn zeigen? Schreib den Typ mal hin!

von samuel (Gast)


Lesenswert?

er soll dann auf einen Parameter von Typ s16 zeigen....also vom typ
"int"

von MSE (Gast)


Lesenswert?

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!

von samuel (Gast)


Lesenswert?

dann bringt der compiler bei mir aber:
"type name is not allowed"

von MSE (Gast)


Lesenswert?

Schreib Deine ganze Zeile hin!

von samuel (Gast)


Lesenswert?

(*s16)comm_tab[mid].ptr=(s16)parametervalue_intern;

von MSE (Gast)


Lesenswert?

versuch
"((*s16)comm_tab[mid]).ptr=(s16)parametervalue_intern;"

Bis morgen!

von samuel (Gast)


Lesenswert?

hm....ist immer noch der gleiche Fehler...aber danke dir

von MSE (Gast)


Lesenswert?

Um da durchzublicken müßte ich größere Teile Deines Quellcodes sehen.
Insbesondere die Deklaration der beteiligten Typen und Variablen.

Gruß, Michael

von Christian (Gast)


Lesenswert?

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 = &parametervalue_intern;

(& zeigt auf die Adresse von parametervalue_intern)

Vorrausgesetzt das comm_tab[mid].ptr ein POINTER ist (*irgentwas)
sollte das gehen ...


Lg


CHW

von OldBug (Gast)


Lesenswert?

@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!

von Philipp Sªsse (Gast)


Lesenswert?

> ((*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?

von OldBug (Gast)


Lesenswert?

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);
[..]

von samuel (Gast)


Lesenswert?

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

von OldBug (Gast)


Lesenswert?

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".

von MSE (Gast)


Lesenswert?

Ich bitte noch einmal darum, dass Du mehr von Deinem Quellcode postest!
Mindestens die Stellen, an denen die beteiligten Typen und Variablen
Deklariert werden.

von OldBug (Gast)


Lesenswert?

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!

von Michael (ein anderer) (Gast)


Lesenswert?

@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;
...

von Michael (ein anderer) (Gast)


Lesenswert?

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....

von samuel (Gast)


Lesenswert?

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,&parameter1},
{"parameter2",TYPS16,&parameter2},
//etc.....
}



switch (comm_tab[mid].type)
    {

case TYPS16:
comm_tab[mid].ptr=&parametervalue_intern;
break;

case TYPU16:
comm_tab[mid].ptr=&parametervalue_intern;
break;

case TYPS32:
comm_tab[mid].ptr=&parametervalue_intern;
break;

case TYPU32:
comm_tab[mid].ptr=&parametervalue_intern;
break;

von samuel (Gast)


Lesenswert?

Habe es gerade ausprobiert:

*(s16 *)(comm_tab[mid].ptr)=parametervalue_intern;

ist genau richtig....


juhu es funktioniert.....vielen Dank an alle!!!

von Michael (ein anderer) (Gast)


Lesenswert?

Aha!

Also, mit:

> comm_tab[mid].ptr=&parametervalue_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;

von OldBug (Gast)


Lesenswert?

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...

von OldBug (Gast)


Lesenswert?

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;
[..]

von nobody0 (Gast)


Lesenswert?

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);

von Rufus T. Firefly (Gast)


Lesenswert?

#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.

von OldBug (Gast)


Lesenswert?

Rufus: Du hast Dir auch Dein Bier verdient, heute ;)

von nobody0 (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.