mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme beim casten


Autor: samuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: MSE (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: samuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: MSE (Gast)
Datum:

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

Autor: samuel (Gast)
Datum:

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

Autor: MSE (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: samuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann bringt der compiler bei mir aber:
"type name is not allowed"

Autor: MSE (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schreib Deine ganze Zeile hin!

Autor: samuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(*s16)comm_tab[mid].ptr=(s16)parametervalue_intern;

Autor: MSE (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
versuch
"((*s16)comm_tab[mid]).ptr=(s16)parametervalue_intern;"

Bis morgen!

Autor: samuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm....ist immer noch der gleiche Fehler...aber danke dir

Autor: MSE (Gast)
Datum:

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

Gruß, Michael

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Philipp Sªsse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
[..]

Autor: samuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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".

Autor: MSE (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Michael (ein anderer) (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
...

Autor: Michael (ein anderer) (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: samuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: samuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe es gerade ausprobiert:

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

ist genau richtig....


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

Autor: Michael (ein anderer) (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
[..]

Autor: nobody0 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus: Du hast Dir auch Dein Bier verdient, heute ;)

Autor: nobody0 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.