Probleme beim casten

Gast #132011
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
Gast #132012
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?
Gast #132015
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!
Gast #132022
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
Gast #132023
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!
Gast #132024
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?
Gast #132025
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);
[..]
Gast #132026
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
Gast #132027
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".
Gast #132030
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;
...
Gast #132031
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....
Gast #132032
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;
Gast #132034
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;
Gast #132035
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...
Gast #132037
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);
Gast #132038
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.
Gast #132040
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren