Verschachtelte Pointer - C Frage

Gast #2519688
Lesenswert?

Hallo Leute,

könnte ihr mir eventuell bei folgender Codezeile weiterhelfen?
1
(*((unsigned long*)&netmask[0]))       = (*((unsigned long*)&cache.netmask[0]));

Netmask ist vom Typ:
1
unsigned char netmask[4];

Mir ist soweit klar, dass er sich die Adresse vom ersten Char holt und 
dies in ein Long packt, also alle 4 Chars im Long hat. Was aber macht 
der erste * bei den Anweisungen?

Danke für die Rückmeldungen :)

mfg Flo
#2519705
Lesenswert?

Im Prinzip (wenn meine eingerosteten C Kenntnisse jetzt nicht purzelbaum 
schlagen) kopiert er doch einfach 4 Bytes (sizeof(long)) von 
cache.netmask nach netmask.
Das funktioniert aber nur wennd ie Bytes gepackt sind und der Prozessor 
byteweise auf den Speicher zugreifen kann.
Typisches Beispiel C zu missbrauchen um 'schneller' zu sein oderf 
weniger Codezeilen zu haben.
Eine Schleife über die 4 Bytes wären besser lesbar und würden auf allen 
Systemen funktionieren.
Gast #2519711
Lesenswert?

Danke für die Antworten :)

Aber wenn ich eine Long Variable einer anderen Long Variable zuordne, 
dann ist das doch eine Wertzuweisung, weil
1
(unsigned long*)&cache.netmask[0]
ist dann doch ein Long mit den entsprechenden Werten, der auch einem 
anderen Long zugewiesen werden können müsste?
Oder hab ich da jetzt ein Denkfehler?

Würde folgendes nicht funktionieren:
1
unsigned long test = (unsigned long*)&cache.netmask[0];
so müsste ich doch in meiner test Variable die Netmask quasi am "Stück" 
stehen haben?

lg Flo
#2519713
Lesenswert?

Flo schrieb:
> Danke für die Antworten :)
>
> Aber wenn ich eine Long Variable einer anderen Long Variable zuordne,
> dann ist das doch eine Wertzuweisung, weil
>
1
(unsigned long*)&cache.netmask[0]
> ist dann doch ein Long mit den entsprechenden Werten, der auch einem
> anderen Long zugewiesen werden können müsste?
> Oder hab ich da jetzt ein Denkfehler?

Der ganze Ausdruck ergibt aber keinen Long.
Der Ausdruck ergibt einen Pointer auf einen Long.

> Würde folgendes nicht funktionieren:
>
1
unsigned long test = (unsigned long*)&cache.netmask[0];

Links steht ein Long, rechts steht ein Pointer
-> kann also nicht funktionieren

Du musst schon ein bischen auch auf die Datentypen achten!
Vor allen Dingen auf die Sterne.
Gast #2519720
Lesenswert?

Sieht irgendwie verdammt kompliziert aus

also 4 byte in ein array schieben,
sich vom ersten byte den Pointer holen,
diesen dann in einen Pointer von einem Long casten,
Um desen dann wieder zu derefenrzieren um an den wert des Longs zu 
kommen.

kann man so machen, gibt aber sicher schönere versionen davon.

Weiso ist netmask nicht gleich ein Long?
Ginge das ggf über ein union?
Ist das nicht ggf sogar gefährlich da nicht portabel? (big / litle 
endion)
#2519731
Lesenswert?

123 schrieb:
> Weiso ist netmask nicht gleich ein Long?
Weil da sowas wie 175.100.101.75 drinsteht.

123 schrieb:
> Ist das nicht ggf sogar gefährlich da nicht portabel? (big / litle
> endion)
Big/little endian wäre hier nicht das Problem, da du bei der Zuweisung 
beide Variablen auf der bleichen Maschine hast. Aber manch Prozessoren 
können auf einzelne Bytes nicht auf ungeraden Adressen zugreifen und da 
krachts dann.
Im Netz benutzt man übrigens die sogenannte "net byte order" das 
entspricht soviel ich weiss dem big endian

Union wäre möglich aber nur wennd as Array gepackt ist.
Ist wie gesagt unnötig, for Schleife tuts auch.
#2519734
Lesenswert?

C-Lerner schrieb:
> Geht das?
>
> unsigned long test = (unsigned long)((unsigned long*)&cache.netmask[0]);

Geht auf einer 32 Bit Maschine, aber du castest einen Pointer in einen 
Long Wert. Du dereferenzierst ihn nicht.
Was willst du damit erreichen?

Zusatz
richtiger wäre eher
unsigned long test = *((unsigned long*)&cache.netmask[0]);
unsigned long *test = (unsigned long*)&cache.netmask[0];
Gast #2519760
Lesenswert?

ahso, der * hinterm Long macht ja quasi einen Long Pointer, der dann als 
Startadresse den vom Array[0] bekommt und dereferenziert gibt er eben 
Long, also die 4 Byte zurück.

Jetzt wirds langsam heller, danke ;)

lg Flo
Gast #2519766
Lesenswert?

Hallo

ok, sowas in dieser Richting meinte ich. Vielen Dank!

>Zusatz
richtiger wäre eher
unsigned long test = *((unsigned long*)&cache.netmask[0]);
unsigned long *test = (unsigned long*)&cache.netmask[0];

Udo Schmitt schrieb:
> Zusatz
> richtiger wäre eher
> unsigned long test = *((unsigned long*)&cache.netmask[0]);
> unsigned long *test = (unsigned long*)&cache.netmask[0];
>

Ich muß da mal damit spielen......und im Debugger anschauen was 
geschieht...
#2519784
Lesenswert?

C-Lerner schrieb:
> Ich muß da mal damit spielen......und im Debugger anschauen was
> geschieht...

Du musst nur den Unterschied verstehen lernen zwischen einem Wert, der 
irgendwo im Speicher steht und dem Zeiger (Pointer) der auf den 
Speicherort zeigt.

long test; // test ist ein long wert, der im Speicher 4 Byte belegt.
long *ptest = &test;  // ptest ist ein zeiger der auf test zeigt.

*ptest = 123; // ich schreibe den Wert 123 in die Stelle auf die der 
Zeiger ptest zeigt.

Da der Zeiger auf die Variable test zeigt steht da jetzt 123 drin.

test    Variable vom Typ long
&test   Die Adresse der Variable test
ptest   Adresse die auf einen long Wert zeigt
*ptest  Der Wert auf den der Zeiger zeigt  (dereferenzieren)
#2519838
Lesenswert?

Ich finde das
1
&netmask[0]
ist unnötig und dadurch ist der gesamte Ausdruck schlecht lesbar.
so gehts auch:
1
netmask
 da ein array ohne das [] ein Zeiger auf den ersten Wert des Arrays ist.
1
*((uint32*)au8_netmask) = *((uint32*)st_cache.au8_netmask);
2
//oder
3
*((uint32*)au8_netmask) = u32_irgendwas;
(möglicherweise kann man auch noch ein Paar Klammern weglassen, da bin 
ich mir im Moment aber nicht ganz sicher)

EDIT: vernünftige Compiler dürften mit solchen Ausdrücken keine Probleme 
haben. Ich habe sowas sowohl auf 8-Bit als auch auf 32-Bit Systemen 
verwendet. Immerhin gibts das casten von Zeigern schon seit über 20 
Jahren in C.
#2519905
Lesenswert?

Benjamin F. schrieb:
> EDIT: vernünftige Compiler dürften mit solchen Ausdrücken keine Probleme
> haben. Ich habe sowas sowohl auf 8-Bit als auch auf 32-Bit Systemen
> verwendet. Immerhin gibts das casten von Zeigern schon seit über 20
> Jahren in C.
Nur das es etwas gibt heisst noch nicht daß es sinnvoll ist. Zumindest 
nicht hier.
Was machst du wenn auf IPv6 umgestellt wird?
Was machst du wenn das Byte Array nicht gepackt ist oder je nach 
Prozessor gar nicht gepackt werden kann?
...

Ich bleibe dabei das ist hier Schweinkramprogrammierung.
#2519963
Lesenswert?

Udo Schmitt schrieb:
> Was machst du wenn auf IPv6 umgestellt wird?
IPv4 Server sind soweit ich weiß mit IPv6 nicht zu erreichen und 
umgekehrt, also muss man sowieso das Programm dementsprechend anpassen 
und man sollte dann auch gleich einen entsprechenden Datentyp 
definieren, z.B. ne union die sowohl v4 als auch v6 aufnehmen kann oder 
nen struct aus enum+union.

Mich würde eher interessieren was du machst wenn du z.B. so einen struct 
über UART verschickst und diesen auf der anderen Seite aus einem 
Byte-Array "wiederherstellen" musst.
1
typedef struct 
2
{
3
  EN_SOMEENUMERATION  en_irgendwas1;
4
  sint16              s16_irgendwas2;
5
  float               f32_irgendwas3;
6
  uint8               au8_irgendwas4[16];
7
  ST_SOMESTRUCT       st_irgendwas5;
8
}ST_MYSTRUCT;

Willst du sowas immer von Hand zusammen Bauen und wenn ja, wie willst du 
das enum und die Gleitkomma-Zahl aus dem Byte-Array bekommen?
#2520000
Lesenswert?

Benjamin F. schrieb:
> Willst du sowas immer von Hand zusammen Bauen und wenn ja, wie willst du
> das enum und die Gleitkomma-Zahl aus dem Byte-Array bekommen?
Was hat das damit zu tun, daß das casten eines byte arrays in einen Long 
nicht überall funktioniert und deshalb auf deutsch Kacke ist?

Zu deinem Beispiel:
Du willst ein enum von einem Rechner zu einem anderen schicken und 
erwartest daß der das noch richtig versteht?
Na viel Spass.
Hast du schon jemals komplexere Daten von einem Computer an einen 
anderen geschickt? Unterschiedlicher Bauart und unterschiedliche 
Betriebssysteme?
Dazu ist ein Protokoll da, daß eindeutig geklärt ist wie Daten zu 
interpretieren sind.
Su sollst es nicht von Hand machen aber du sollst eine Funktion 
schreiben die deine komplexe Daten in einer klar definierten Art und 
Weise in ein Byte Array schreibt und eine zweite die das auch wieder 
exakt so liest.
Dann kann man sogar von einem PC über eine Unix Kiste auf eine Vax mit 
MVS oder einen IBM Großrechner kommunizieren.
Wenn du es noch weiter treiben willst schau dir mal z.B. SOAP an. 
Stichwort "Webservice Kommunikationsprotokolle"
#2520145
Lesenswert?

Udo Schmitt schrieb:
> Benjamin F. schrieb:
>> Willst du sowas immer von Hand zusammen Bauen und wenn ja, wie willst du
>> das enum und die Gleitkomma-Zahl aus dem Byte-Array bekommen?
> Was hat das damit zu tun, daß das casten eines byte arrays in einen Long
> nicht überall funktioniert und deshalb auf deutsch Kacke ist?

hast du dafür ein beispiel? wenn es beim casten von zeigern auf dem 
eigenen system zu fehlern kommt ist imo der compiler ganz ganz großer 
mist.

> Zu deinem Beispiel:
> Du willst ein enum von einem Rechner zu einem anderen schicken und
> erwartest daß der das noch richtig versteht?
> Na viel Spass.
> Hast du schon jemals komplexere Daten von einem Computer an einen
> anderen geschickt? Unterschiedlicher Bauart und unterschiedliche
> Betriebssysteme?
> Dazu ist ein Protokoll da, daß eindeutig geklärt ist wie Daten zu
> interpretieren sind.
> Su sollst es nicht von Hand machen aber du sollst eine Funktion
> schreiben die deine komplexe Daten in einer klar definierten Art und
> Weise in ein Byte Array schreibt und eine zweite die das auch wieder
> exakt so liest.
> Dann kann man sogar von einem PC über eine Unix Kiste auf eine Vax mit
> MVS oder einen IBM Großrechner kommunizieren.
> Wenn du es noch weiter treiben willst schau dir mal z.B. SOAP an.
> Stichwort "Webservice Kommunikationsprotokolle"

das man bei unterschiedlichen system und verschiedenen compilern noch 
mehr beachten muss ist klar aber was hat das damit zu tun das casten von 
zeigern generell zu verteufeln? mal davon abgesehen das es hier um uC 
geht und nicht um PCs...
#2520163
Lesenswert?

Benjamin F. schrieb:
> hast du dafür ein beispiel? wenn es beim casten von zeigern auf dem
> eigenen system zu fehlern kommt ist imo der compiler ganz ganz großer
> mist.

Ich hatte es oben schon gesagt. Es gibt Systeme (auch zumindeste einige 
ältere 16 und 32 Bit Controller (ich glaube bestimmte DSPs) die 8 Bit 
Werte nicht wahlfrei hintereinander ablegen können/konnten. Dadurch sind 
Füllbytes/ungenutzte Bytes zwischen den einzelnen Bytes des Arrays.
Genau auf solchen Meschinen kracht sowas dann.
Also lässt man so einen Blödsinn eine for Schleife hat eine Zeile mehr 
und da ist es klar.

Andere Systeme brauchen deutlich mehr Zeit wenn sie byteweise auf 
ungerade Adressen zugreifen sollen, wenn du also den Compiler auf 
Geschwindigkeit optimieren lässt könnte es durchaus sein, daß er ein 
byte array nicht gepackt ablegt, sondern auch Füllbytes vergibt so daß 
der Zugriff schneller ist, dann krachts auch.

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